Skip to content

Commit

Permalink
feat: add empty-view package (#362)
Browse files Browse the repository at this point in the history
Adds empty view package that contains four kind of empty view
components. In order to have a consisitent user experience across all
our applications, we need to use these common components when there is
no data to present.
Also adds useMediaQuery hook which is used in `MainEmptyView`. And it
will be used when we implement the responsive design.
  • Loading branch information
boilund authored Dec 2, 2024
1 parent 61a78bd commit 2c238de
Show file tree
Hide file tree
Showing 24 changed files with 790 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The React packages are based on the `@fluentui/react-*` **v9** packages.
- [`@axiscommunications/fluent-stepper`](components/stepper/docs/README.md) - a stepper component for building e.g. wizards
- [`@axiscommunications/fluent-slider`](components/slider/docs/README.md) - various slider components
- [`@axiscommunications/fluent-topbar`](components/topbar/docs/README.md) - top level bar that hosts app and organization selection and menus
- [`@axiscommunications/fluent-empty-view`](components/empty-view/docs/README.md) - Empty view component that displays when there is no data
- [`@axiscommunications/fluent-password-input`](components/password-input/docs/README.md) - a password input that lets you reveal the password
- [`@axiscommunications/fluent-illustrations`](illustrations/docs/README.md) - axis branded illustrations

Expand Down
8 changes: 8 additions & 0 deletions components/empty-view/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": ["../../.eslintrc.json"],
"root": true,
"ignorePatterns": ["lib", "**/*.js"],
"parserOptions": {
"project": ["./tsconfig.src.json"]
}
}
9 changes: 9 additions & 0 deletions components/empty-view/depcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
ignores:
[
"react-dom",
"typescript",
"@testing-library/jest-dom",
"@griffel/react",
"@vitest/coverage-c8",
]
skip-missing: true
62 changes: 62 additions & 0 deletions components/empty-view/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Empty view - @axiscommunications/fluent-empty-view

Empty view is a component that displays when there is no data.

## How to install

```sh
yarn add @axiscommunications/fluent-empty-view
```

```sh
npm install @axiscommunications/fluent-empty-view
```

## Usage

```ts
import { MainEmptyView, PanelEmptyView, SubmenuEmptyView, DialogEmptyView } from "@axiscommunications/fluent-empty-view";

export const MainEmptyViewExample = () => {
return (
<MainEmptyView
illustration="no-connection"
title="There's no connection"
after={
<Button icon={<ArrowSyncRegular />} onClick={reload}>
"Try again"
</Button>
}
>
"You don't seem to have any connection to the internet. Check your network settings and try again."
</MainEmptyView>
);
};

export const PanelEmptyViewExample = () => {
return (
<PanelEmptyView illustration="add-user-profile" title="No roles have been assigned to the user">
"Assign roles and grant access to users to provide them with the necessary permissions to access resources within the organization."
</PanelEmptyView>
);
};

export const SubmenuEmptyViewExample = () => {
return (
<SubmenuEmptyView illustration="no-match" title="No matching results">
"We couldn't find any folders matching your search."
</SubmenuEmptyView>
);
};

export const DialogEmptyViewExample = () => {
return (
<DialogContent>
<div style={{ height: '240px' }}>
<DialogEmptyView title="No roles">"You haven’t created any roles yet."</DialogEmptyView>
</div>
</DialogContent>
);
};
```

47 changes: 47 additions & 0 deletions components/empty-view/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@axiscommunications/fluent-empty-view",
"version": "10.3.0",
"description": "Empty view for Fluent UI v9",
"homepage": "https://github.com/AxisCommunications/fluent-components#readme",
"repository": {
"type": "git",
"url": "https://github.com/AxisCommunications/fluent-components.git",
"directory": "components/empty-view"
},
"license": "MIT",
"author": "Axis Communications AB",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"files": [
"lib"
],
"scripts": {
"prebuild": "pnpm run -C ../../illustrations build",
"build": "pnpm prebuild && pnpm build:cjs && pnpm build:esm",
"build:cjs": "tsc --module commonjs --outDir lib/cjs",
"build:esm": "tsc",
"check:unused-deps": "depcheck . --config=depcheck.yml",
"lint": "tsc --noEmit && eslint . --cache"
},
"devDependencies": {
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"eslint": "^8.57.1",
"jsdom": "^22.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^4.5.5"
},
"peerDependencies": {
"@fluentui/react-components": "^9.55.1",
"react": ">=16.8.0 <19.0.0",
"react-dom": ">=16.8.0 <19.0.0"
},
"dependencies": {
"@axiscommunications/fluent-hooks": "workspace: *",
"@axiscommunications/fluent-illustrations": "workspace:*"
},
"publishConfig": {
"registry": "https://npm.pkg.github.com/"
}
}
66 changes: 66 additions & 0 deletions components/empty-view/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {
AddUserProfileDark,
AddUserProfileLight,
bundleIllustrationSmart,
DataDark,
DataLight,
DevicesDark,
DevicesLight,
EmptyFolderDark,
EmptyFolderLight,
EmptyGeneralDark,
EmptyGeneralLight,
EmptySpaceDark,
EmptySpaceLight,
FileMissingDark,
FileMissingLight,
NoAccessDark,
NoAccessLight,
NoConnectionDark,
NoConnectionLight,
NoContentDark,
NoContentLight,
NoMatchDark,
NoMatchLight,
NoSitesDark,
NoSitesLight,
NotFoundDark,
NotFoundLight,
SettingsDark,
SettingsLight,
SuccessDark,
SuccessLight,
TeamDark,
TeamLight,
UnderConstructionDark,
UnderConstructionLight,
} from "@axiscommunications/fluent-illustrations";

export const Illustration: Record<
string,
ReturnType<typeof bundleIllustrationSmart>
> = {
"add-user-profile": bundleIllustrationSmart(
AddUserProfileDark,
AddUserProfileLight
),
data: bundleIllustrationSmart(DataDark, DataLight),
devices: bundleIllustrationSmart(DevicesDark, DevicesLight),
"empty-folder": bundleIllustrationSmart(EmptyFolderDark, EmptyFolderLight),
"empty-space": bundleIllustrationSmart(EmptySpaceDark, EmptySpaceLight),
"file-missing": bundleIllustrationSmart(FileMissingDark, FileMissingLight),
general: bundleIllustrationSmart(EmptyGeneralDark, EmptyGeneralLight),
"no-access": bundleIllustrationSmart(NoAccessDark, NoAccessLight),
"no-connection": bundleIllustrationSmart(NoConnectionDark, NoConnectionLight),
"no-content": bundleIllustrationSmart(NoContentDark, NoContentLight),
"no-match": bundleIllustrationSmart(NoMatchDark, NoMatchLight),
"no-sites": bundleIllustrationSmart(NoSitesDark, NoSitesLight),
"not-found": bundleIllustrationSmart(NotFoundDark, NotFoundLight),
settings: bundleIllustrationSmart(SettingsDark, SettingsLight),
success: bundleIllustrationSmart(SuccessDark, SuccessLight),
team: bundleIllustrationSmart(TeamDark, TeamLight),
"under-construction": bundleIllustrationSmart(
UnderConstructionDark,
UnderConstructionLight
),
} as const;
6 changes: 6 additions & 0 deletions components/empty-view/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export {
DialogEmptyView,
MainEmptyView,
PanelEmptyView,
SubmenuEmptyView,
} from "./view";
50 changes: 50 additions & 0 deletions components/empty-view/src/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { makeStyles, shorthands, tokens } from "@fluentui/react-components";

export const useStyles = makeStyles({
container: {
display: "flex",
flexDirection: "column",
alignItems: "center",
textAlign: "center",
...shorthands.margin("auto"),
height: "100%",
maxWidth: "500px",
},
fixedSpacer: {
height: "60px",
},
spacer: {
flexGrow: 1,
},
illustrationLarge: {
flex: "none",
height: "160px",
width: "230px",
marginBottom: tokens.spacingVerticalS,
},
illustrationMedium: {
flex: "none",
height: "140px",
width: "200px",
marginBottom: tokens.spacingVerticalXS,
},
illustrationSmall: {
flex: "none",
height: "80px",
width: "115px",
marginBottom: tokens.spacingVerticalXS,
},
title: {
color: tokens.colorNeutralForeground2,
textAlign: "center",
marginBottom: tokens.spacingVerticalS,
},
text: {
color: tokens.colorNeutralForeground2,
textAlign: "center",
marginBottom: tokens.spacingVerticalL,
},
after: {
verticalAlign: "middle",
},
});
17 changes: 17 additions & 0 deletions components/empty-view/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { PropsWithChildren, ReactNode } from "react";

import { Illustration } from "./constants";

export type IllustrationKind = keyof typeof Illustration;

export interface ContentProps {
readonly body: ReactNode;
readonly illustration: IllustrationKind;
readonly title: string;
}

export type EmptyViewProps = PropsWithChildren<{
readonly after?: ReactNode;
readonly illustration: IllustrationKind;
readonly title: string;
}>;
Loading

0 comments on commit 2c238de

Please sign in to comment.