Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upcoming: [M3-8638] - Introduce the new (at)linode/ui package #11057

Merged
merged 10 commits into from
Oct 10, 2024
33 changes: 32 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
lint:
strategy:
matrix:
package: ["linode-manager", "@linode/api-v4", "@linode/validation"]
package: ["linode-manager", "@linode/api-v4", "@linode/validation", "@linode/ui"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -191,6 +191,37 @@ jobs:
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/search run test

test-ui:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20.17"
- uses: actions/cache@v4
with:
path: |
**/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/ui run test

typecheck-ui:
runs-on: ubuntu-latest
needs: build-sdk
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20.17"
- uses: actions/cache@v4
with:
path: |
**/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
- run: yarn --frozen-lockfile
- run: yarn workspace @linode/ui run typecheck

typecheck-manager:
runs-on: ubuntu-latest
needs: build-sdk
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

## Overview

This repository is home to the Akamai Connected **[Cloud Manager](https://cloud.linode.com)** and related [`@linode/api-v4`](packages/api-v4/) and [`@linode/validation`](packages/validation/) Typescript packages.
This repository is home to the Akamai Connected **[Cloud Manager](https://cloud.linode.com)** and related [`@linode/api-v4`](packages/api-v4/), [`@linode/validation`](packages/validation/) and [`@linode/ui`](packages/ui/) Typescript packages.

## Developing Locally

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
"up": "yarn install:all && yarn build:validation && yarn build:sdk && yarn start:all",
"up:expose": "yarn install:all && yarn build:validation && yarn build:sdk && yarn start:all:expose",
"dev": "yarn install:all && yarn start:all",
"start:all": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start\"",
"start:all:expose": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start:expose\"",
"start:all": "concurrently -n api-v4,validation,ui,manager -c blue,yellow,magenta,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace @linode/ui start\" \"yarn workspace linode-manager start\"",
"start:all:expose": "concurrently -n api-v4,validation,ui,manager -c blue,yellow,magenta,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace @linode/ui start\" \"yarn workspace linode-manager start:expose\"",
"start:manager": "yarn workspace linode-manager start",
"start:manager:ci": "yarn workspace linode-manager start:ci",
"clean": "rm -rf node_modules && rm -rf packages/@linode/api-v4/node_modules && rm -rf packages/manager/node_modules && rm -rf packages/@linode/validation/node_modules",
Expand Down
1 change: 1 addition & 0 deletions packages/manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@linode/api-v4": "*",
"@linode/design-language-system": "^2.6.1",
"@linode/search": "*",
"@linode/ui": "*",
"@linode/validation": "*",
"@lukemorales/query-key-factory": "^1.3.4",
"@mui/icons-material": "^5.14.7",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BetaChip } from '@linode/ui';
import Grid from '@mui/material/Unstable_Grid2';
import * as React from 'react';
import { Link, useLocation } from 'react-router-dom';
Expand All @@ -22,7 +23,6 @@ import VPC from 'src/assets/icons/entityIcons/vpc.svg';
import TooltipIcon from 'src/assets/icons/get_help.svg';
import Longview from 'src/assets/icons/longview.svg';
import AkamaiLogo from 'src/assets/logo/akamai-logo.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Box } from 'src/components/Box';
import { Divider } from 'src/components/Divider';
import { useIsACLPEnabled } from 'src/features/CloudPulse/Utils/utils';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BetaChip } from '@linode/ui';
import { createDatabaseSchema } from '@linode/validation/lib/databases.schema';
import Grid from '@mui/material/Unstable_Grid2';
import { createLazyRoute } from '@tanstack/react-router';
Expand All @@ -10,7 +11,6 @@ import { makeStyles } from 'tss-react/mui';
import MongoDBIcon from 'src/assets/icons/mongodb.svg';
import MySQLIcon from 'src/assets/icons/mysql.svg';
import PostgreSQLIcon from 'src/assets/icons/postgresql.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Button } from 'src/components/Button/Button';
import { CircleProgress } from 'src/components/CircleProgress';
import { Divider } from 'src/components/Divider';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BetaChip } from '@linode/ui';
import { useTheme } from '@mui/material/styles';
import * as React from 'react';

import LogoWhite from 'src/assets/icons/db-logo-white.svg';
import Logo from 'src/assets/icons/db-logo.svg';
import { BetaChip } from 'src/components/BetaChip/BetaChip';
import { Box } from 'src/components/Box';
import { Typography } from 'src/components/Typography';

Expand Down
18 changes: 18 additions & 0 deletions packages/ui/.changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changesets

This directory gets auto-populated when running `yarn changeset`.
You can however add your changesets manually as well, knowing that the [TYPE] is limited to the following options `Added`, `Fixed`, `Changed`, `Removed`, `Tech Stories`, `Tests`, `Upcoming Features` and follow this format:

```md
---
"@linode/[PACKAGE]": [TYPE]
---

My PR Description ([#`PR number`](`PR link`))
```

You must commit them to the repo so they can be picked up for the changelog generation.

This directory get wiped out when running `yarn generate-changelog`.

See `changeset.mjs` for implementation details.
5 changes: 5 additions & 0 deletions packages/ui/.changeset/pr-11057-added-1728496448213.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@linode/ui": Added
---

new `@linode/ui` package with `BetaChip` as the first component ([#11057](https://github.com/linode/manager/pull/11057))
75 changes: 75 additions & 0 deletions packages/ui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"ignorePatterns": [
"node_modules",
"lib",
"index.js",
"!.eslintrc.js"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"warnOnUnsupportedTypeScriptVersion": true
},
"plugins": [
"@typescript-eslint",
"sonarjs",
"prettier",
"@linode/eslint-plugin-cloud-manager"
],
"extends": [
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:sonarjs/recommended",
"plugin:prettier/recommended"
],
"rules": {
"no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_"
}
],
"no-unused-expressions": "warn",
"no-bitwise": "error",
"no-caller": "error",
"no-eval": "error",
"no-throw-literal": "warn",
"no-loop-func": "error",
"no-await-in-loop": "error",
"array-callback-return": "error",
"no-invalid-this": "off",
"no-new-wrappers": "error",
"no-restricted-imports": [
"error",
"rxjs"
],
"no-console": "error",
"no-undef-init": "off",
"radix": "error",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-namespace": "warn",
"@typescript-eslint/camelcase": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-empty-interface": "warn",
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/interface-name-prefix": "off",
"sonarjs/cognitive-complexity": "warn",
"sonarjs/no-duplicate-string": "warn",
"sonarjs/prefer-immediate-return": "warn",
"sonarjs/no-identical-functions": "warn",
"sonarjs/no-redundant-jump": "warn",
"sonarjs/no-small-switch": "warn",
"no-multiple-empty-lines": "error",
"curly": "warn",
"sort-keys": "off",
"comma-dangle": "off",
"no-trailing-spaces": "warn",
"no-mixed-requires": "warn",
"spaced-comment": "warn",
"object-shorthand": "warn",
"prettier/prettier": "warn"
}
}
4 changes: 4 additions & 0 deletions packages/ui/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"printWidth": 80,
"singleQuote": true
}
Empty file added packages/ui/CHANGELOG.md
Empty file.
61 changes: 61 additions & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@linode/ui",
"author": "Linode",
"description": "Linode UI component library",
"version": "0.0.1",
"type": "module",
"main": "src/index.ts",
"module": "src/index.ts",
"types": "src/index.ts",
"exports": {
".": "./src/index.ts"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/linode/manager/tree/develop/packages/ui"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.7",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"scripts": {
"start": "tsc -w --preserveWatchOutput",
"lint": "eslint . --quiet --ext .js,.ts,.tsx",
"typecheck": "tsc",
"precommit": "lint-staged",
"test": "vitest run",
"test:watch": "vitest",
"test:debug": "node --inspect-brk scripts/test.js --runInBand",
"coverage": "vitest run --coverage && open coverage/index.html",
"coverage:summary": "vitest run --coverage.enabled --reporter=junit --coverage.reporter=json-summary"
},
"lint-staged": {
"*.{ts,tsx,js}": [
"prettier --write",
"eslint --ext .js,.ts,.tsx --quiet"
]
},
"devDependencies": {
"@linode/eslint-plugin-cloud-manager": "^0.0.5",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "~6.4.2",
"@testing-library/react": "~16.0.0",
"@types/node": "^12.7.1",
"@types/react": "^18.2.55",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitest/ui": "^2.1.1",
"eslint": "^7.1.0",
"eslint-config-prettier": "~8.1.0",
"eslint-plugin-prettier": "~3.3.1",
"eslint-plugin-sonarjs": "^0.5.0",
"lint-staged": "^15.2.9",
"prettier": "~2.2.1",
"vitest": "^2.1.1"
}
}
33 changes: 33 additions & 0 deletions packages/ui/src/components/BetaChip/BetaChip.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { fireEvent, render } from '@testing-library/react';
import React from 'react';

import { BetaChip } from './BetaChip';

import { expect, vi, describe, it } from 'vitest';
import '@testing-library/jest-dom/vitest';

describe('BetaChip', () => {
hkhalil-akamai marked this conversation as resolved.
Show resolved Hide resolved
it('renders with default color', () => {
const { getByTestId } = render(<BetaChip />);
const betaChip = getByTestId('betaChip');
expect(betaChip).toBeInTheDocument();
expect(betaChip).toHaveStyle('background-color: rgba(0, 0, 0, 0.08)');
});

it('renders with primary color', () => {
const { getByTestId } = render(<BetaChip color="primary" />);
const betaChip = getByTestId('betaChip');
expect(betaChip).toBeInTheDocument();
expect(betaChip).toHaveStyle('background-color: rgb(25, 118, 210)');
});

it('triggers an onClick callback', () => {
const onClickMock = vi.fn();
const { getByTestId } = render(
<BetaChip color="default" onClick={onClickMock} />
);
const betaChip = getByTestId('betaChip');
fireEvent.click(betaChip);
expect(onClickMock).toHaveBeenCalledTimes(1);
});
});
62 changes: 62 additions & 0 deletions packages/ui/src/components/BetaChip/BetaChip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { styled } from '@mui/material/styles';
import * as React from 'react';
import { Chip } from '../Chip';
import type { ChipProps } from '@mui/material';

export interface BetaChipProps
extends Omit<
ChipProps,
| 'avatar'
| 'clickable'
| 'deleteIcon'
| 'disabled'
| 'icon'
| 'label'
| 'onDelete'
| 'outlineColor'
| 'size'
| 'variant'
> {
/**
* The color of the chip.
* default renders a gray chip, primary renders a blue chip.
*/
color?: 'default' | 'primary';
}

/**
* ## Usage
*
* Beta chips label features that are not yet part of Cloud Manager's core supported functionality.<br>
* **Example:** A beta chip may appear in the [primary navigation](https://github.com/linode/manager/pull/8104#issuecomment-1309334374),
* breadcrumbs, [banners](/docs/components-notifications-dismissible-banners--beta-banners), tabs, and/or plain text to designate beta functionality.<br>
* **Visual style:** bold, capitalized text; reduced height, letter spacing, and font size; solid color background.
*
*/
export const BetaChip = (props: BetaChipProps) => {
const { color } = props;

return (
<StyledBetaChip
{...props}
color={color}
data-testid="betaChip"
label="beta"
/>
);
};

const StyledBetaChip = styled(Chip, {
label: 'StyledBetaChip',
})<BetaChipProps>(({ theme }) => ({
'& .MuiChip-label': {
padding: 0,
},
fontSize: '0.625rem',
fontFamily: '"LatoWebBold", sans-serif', // TODO: remove hardcoded font once theme is added to this package
Copy link
Contributor Author

@hkhalil-akamai hkhalil-akamai Oct 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

theme.font is a custom declaration from our theme.ts file

height: 16,
letterSpacing: '.25px',
marginLeft: theme.spacing(0.5),
padding: theme.spacing(0.5),
textTransform: 'uppercase',
}));
1 change: 1 addition & 0 deletions packages/ui/src/components/BetaChip/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './BetaChip';
8 changes: 8 additions & 0 deletions packages/ui/src/components/Chip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { default as _Chip } from '@mui/material/Chip';
import * as React from 'react';

import type { ChipProps } from '@mui/material/Chip';

export const Chip = (props: ChipProps) => {
return <_Chip {...props} />;
};
2 changes: 2 additions & 0 deletions packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './Chip';
export * from './BetaChip';
1 change: 1 addition & 0 deletions packages/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components';
Loading