Skip to content

Commit

Permalink
scaffold react-skeleton components (#26640)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomi-msft authored Feb 3, 2023
1 parent 8edde8f commit f621406
Show file tree
Hide file tree
Showing 49 changed files with 694 additions and 5 deletions.
14 changes: 14 additions & 0 deletions packages/react-components/react-skeleton/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const rootMain = require('../../../../.storybook/main');

module.exports = /** @type {Omit<import('../../../../.storybook/main'), 'typescript'|'babel'>} */ ({
...rootMain,
stories: [...rootMain.stories, '../stories/**/*.stories.mdx', '../stories/**/index.stories.@(ts|tsx)'],
addons: [...rootMain.addons],
webpackFinal: (config, options) => {
const localConfig = { ...rootMain.webpackFinal(config, options) };

// add your own webpack tweaks if needed

return localConfig;
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as rootPreview from '../../../../.storybook/preview';

/** @type {typeof rootPreview.decorators} */
export const decorators = [...rootPreview.decorators];

/** @type {typeof rootPreview.parameters} */
export const parameters = { ...rootPreview.parameters };
10 changes: 10 additions & 0 deletions packages/react-components/react-skeleton/.storybook/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "",
"allowJs": true,
"checkJs": true,
"types": ["static-assets", "environment", "storybook__addons"]
},
"include": ["../stories/**/*.stories.ts", "../stories/**/*.stories.tsx", "*.js"]
}
85 changes: 85 additions & 0 deletions packages/react-components/react-skeleton/etc/react-skeleton.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,91 @@
```ts

import type { ComponentProps } from '@fluentui/react-utilities';
import type { ComponentState } from '@fluentui/react-utilities';
import type { ForwardRefComponent } from '@fluentui/react-utilities';
import * as React_2 from 'react';
import type { Slot } from '@fluentui/react-utilities';
import type { SlotClassNames } from '@fluentui/react-utilities';

// @public
export const renderSkeleton_unstable: (state: SkeletonState) => JSX.Element;

// @public
export const renderSkeletonCircle_unstable: (state: SkeletonCircleState) => JSX.Element;

// @public
export const renderSkeletonLine_unstable: (state: SkeletonLineState) => JSX.Element;

// @public
export const Skeleton: ForwardRefComponent<SkeletonProps>;

// @public
export const SkeletonCircle: ForwardRefComponent<SkeletonCircleProps>;

// @public (undocumented)
export const skeletonCircleClassNames: SlotClassNames<SkeletonCircleSlots>;

// @public
export type SkeletonCircleProps = ComponentProps<SkeletonCircleSlots> & {};

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

// @public
export type SkeletonCircleState = ComponentState<SkeletonCircleSlots>;

// @public (undocumented)
export const skeletonClassNames: SlotClassNames<SkeletonSlots>;

// @public
export const SkeletonLine: ForwardRefComponent<SkeletonLineProps>;

// @public (undocumented)
export const skeletonLineClassNames: SlotClassNames<SkeletonLineSlots>;

// @public
export type SkeletonLineProps = ComponentProps<SkeletonLineSlots> & {};

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

// @public
export type SkeletonLineState = ComponentState<SkeletonLineSlots>;

// @public
export type SkeletonProps = ComponentProps<SkeletonSlots> & {};

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

// @public
export type SkeletonState = ComponentState<SkeletonSlots>;

// @public
export const useSkeleton_unstable: (props: SkeletonProps, ref: React_2.Ref<HTMLElement>) => SkeletonState;

// @public
export const useSkeletonCircle_unstable: (props: SkeletonCircleProps, ref: React_2.Ref<HTMLElement>) => SkeletonCircleState;

// @public
export const useSkeletonCircleStyles_unstable: (state: SkeletonCircleState) => SkeletonCircleState;

// @public
export const useSkeletonLine_unstable: (props: SkeletonLineProps, ref: React_2.Ref<HTMLElement>) => SkeletonLineState;

// @public
export const useSkeletonLineStyles_unstable: (state: SkeletonLineState) => SkeletonLineState;

// @public
export const useSkeletonStyles_unstable: (state: SkeletonState) => SkeletonState;

// (No @packageDocumentation comment for this package)

```
4 changes: 3 additions & 1 deletion packages/react-components/react-skeleton/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"lint": "just-scripts lint",
"test": "jest --passWithNoTests",
"generate-api": "tsc -p ./tsconfig.lib.json --emitDeclarationOnly && just-scripts api-extractor",
"type-check": "tsc -b tsconfig.json"
"type-check": "tsc -b tsconfig.json",
"storybook": "start-storybook",
"start": "yarn storybook"
},
"devDependencies": {
"@fluentui/eslint-plugin": "*",
Expand Down
1 change: 1 addition & 0 deletions packages/react-components/react-skeleton/src/Skeleton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/Skeleton/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/SkeletonCircle/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/SkeletonLine/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 { Skeleton } from './Skeleton';
import { isConformant } from '../../testing/isConformant';

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

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

it('renders a default state', () => {
const result = render(<Skeleton>Default Skeleton</Skeleton>);
expect(result.container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';
import { useSkeleton_unstable } from './useSkeleton';
import { renderSkeleton_unstable } from './renderSkeleton';
import { useSkeletonStyles_unstable } from './useSkeletonStyles';
import type { SkeletonProps } from './Skeleton.types';
import type { ForwardRefComponent } from '@fluentui/react-utilities';

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

useSkeletonStyles_unstable(state);
return renderSkeleton_unstable(state);
});

Skeleton.displayName = 'Skeleton';
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 SkeletonSlots = {
root: Slot<'div'>;
};

/**
* Skeleton Props
*/
export type SkeletonProps = ComponentProps<SkeletonSlots> & {};

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

exports[`Skeleton renders a default state 1`] = `
<div>
<div
class="fui-Skeleton"
>
Default Skeleton
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './Skeleton';
export * from './Skeleton.types';
export * from './renderSkeleton';
export * from './useSkeleton';
export * from './useSkeletonStyles';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as React from 'react';
import { getSlots } from '@fluentui/react-utilities';
import type { SkeletonState, SkeletonSlots } from './Skeleton.types';

/**
* Render the final JSX of Skeleton
*/
export const renderSkeleton_unstable = (state: SkeletonState) => {
const { slots, slotProps } = getSlots<SkeletonSlots>(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 { SkeletonProps, SkeletonState } from './Skeleton.types';

/**
* Create the state required to render Skeleton.
*
* The returned state can be modified with hooks such as useSkeletonStyles_unstable,
* before being passed to renderSkeleton_unstable.
*
* @param props - props from this instance of Skeleton
* @param ref - reference to root HTMLElement of Skeleton
*/
export const useSkeleton_unstable = (props: SkeletonProps, ref: React.Ref<HTMLElement>): SkeletonState => {
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 { SkeletonSlots, SkeletonState } from './Skeleton.types';
import type { SlotClassNames } from '@fluentui/react-utilities';

export const skeletonClassNames: SlotClassNames<SkeletonSlots> = {
root: 'fui-Skeleton',
// TODO: add class names for all slots on SkeletonSlots.
// Should be of the form `<slotName>: 'fui-Skeleton__<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 Skeleton slots based on the state
*/
export const useSkeletonStyles_unstable = (state: SkeletonState): SkeletonState => {
const styles = useStyles();
state.root.className = mergeClasses(skeletonClassNames.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;
};
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 { SkeletonCircle } from './SkeletonCircle';
import { isConformant } from '../../testing/isConformant';

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

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

it('renders a default state', () => {
const result = render(<SkeletonCircle>Default SkeletonCircle</SkeletonCircle>);
expect(result.container).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';
import { useSkeletonCircle_unstable } from './useSkeletonCircle';
import { renderSkeletonCircle_unstable } from './renderSkeletonCircle';
import { useSkeletonCircleStyles_unstable } from './useSkeletonCircleStyles';
import type { SkeletonCircleProps } from './SkeletonCircle.types';
import type { ForwardRefComponent } from '@fluentui/react-utilities';

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

useSkeletonCircleStyles_unstable(state);
return renderSkeletonCircle_unstable(state);
});

SkeletonCircle.displayName = 'SkeletonCircle';
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 SkeletonCircleSlots = {
root: Slot<'div'>;
};

/**
* SkeletonCircle Props
*/
export type SkeletonCircleProps = ComponentProps<SkeletonCircleSlots> & {};

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

exports[`SkeletonCircle renders a default state 1`] = `
<div>
<div
class="fui-SkeletonCircle"
>
Default SkeletonCircle
</div>
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './SkeletonCircle';
export * from './SkeletonCircle.types';
export * from './renderSkeletonCircle';
export * from './useSkeletonCircle';
export * from './useSkeletonCircleStyles';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as React from 'react';
import { getSlots } from '@fluentui/react-utilities';
import type { SkeletonCircleState, SkeletonCircleSlots } from './SkeletonCircle.types';

/**
* Render the final JSX of SkeletonCircle
*/
export const renderSkeletonCircle_unstable = (state: SkeletonCircleState) => {
const { slots, slotProps } = getSlots<SkeletonCircleSlots>(state);

// TODO Add additional slots in the appropriate place
return <slots.root {...slotProps.root} />;
};
Loading

0 comments on commit f621406

Please sign in to comment.