├── .babelrc ├── .env.example ├── .eslintrc ├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── chromatic.yml │ ├── ci.yml │ ├── closeStalePR.yml │ ├── pr.yml │ └── storybook.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── .storybook ├── main.js ├── manager-head.html ├── manager.js ├── orcsTheme.js ├── preview-head.html ├── preview.js └── static │ └── CNAME ├── LICENSE ├── README.md ├── __mocks__ ├── @fortawesome │ └── react-fontawesome.js ├── fileMock.js └── styleMock.js ├── audit-ci-strict.json ├── audit-ci.json ├── config └── jest │ ├── cssTransform.js │ └── fileTransform.js ├── interplay └── interplay.json ├── lib ├── 01-Intro.mdx ├── Colour.mdx ├── GlobalStyles.js ├── Spacing.mdx ├── SystemThemeProvider.js ├── assets │ ├── Colour │ │ ├── Colour.stories.js │ │ └── index.js │ └── Images │ │ └── orcs.png ├── components.test.js ├── components │ ├── ActionsMenu │ │ ├── ActionsMenu.animations.js │ │ ├── ActionsMenu.mdx │ │ ├── ActionsMenu.stories.js │ │ ├── index.js │ │ └── useActionMenu.js │ ├── Avatar │ │ ├── Avatar.mdx │ │ ├── Avatar.stories.js │ │ └── index.js │ ├── Badge │ │ ├── Badge.mdx │ │ ├── Badge.stories.js │ │ └── index.js │ ├── Box │ │ ├── Box.mdx │ │ ├── Box.stories.js │ │ └── index.js │ ├── Button │ │ ├── Button.mdx │ │ ├── Button.stories.js │ │ ├── ButtonLink.stories.js │ │ └── index.js │ ├── ButtonGroup │ │ ├── ButtonGroup.mdx │ │ ├── ButtonGroup.stories.js │ │ ├── ButtonGroupIteam.mdx │ │ ├── ButtonGroupItem.stories.js │ │ └── index.js │ ├── Card │ │ ├── Card.mdx │ │ ├── Card.stories.js │ │ └── index.js │ ├── Checkbox │ │ ├── Checkbox.mdx │ │ ├── Checkbox.stories.js │ │ └── index.js │ ├── DatePicker │ │ ├── DatePicker.mdx │ │ ├── DatePicker.stories.js │ │ └── index.js │ ├── Divider │ │ ├── Divider.mdx │ │ ├── Divider.stories.js │ │ └── index.js │ ├── Expandable │ │ ├── Expandable.mdx │ │ ├── Expandable.stories.js │ │ ├── index.js │ │ └── readme.md │ ├── Flex │ │ ├── Flex.mdx │ │ ├── Flex.stories.js │ │ ├── FlexItem.mdx │ │ ├── FlexItem.stories.js │ │ └── index.js │ ├── FloatingPanels │ │ ├── FloatingPanels.mdx │ │ ├── FloatingPanels.stories.js │ │ ├── FloatingPanels.styles.js │ │ ├── Panel.js │ │ └── index.js │ ├── Grid │ │ ├── Grid.mdx │ │ ├── Grid.stories.js │ │ └── index.js │ ├── Header │ │ ├── Header.mdx │ │ ├── Header.stories.js │ │ ├── Header.styles.js │ │ ├── UserMenu.js │ │ └── index.js │ ├── HeaderComplex │ │ ├── HeaderComplex.mdx │ │ ├── HeaderComplex.stories.js │ │ └── index.js │ ├── HeaderSimple │ │ ├── HeaderSimple.mdx │ │ ├── HeaderSimple.stories.js │ │ └── index.js │ ├── Icon │ │ ├── Icon.mdx │ │ ├── Icon.stories.js │ │ └── index.js │ ├── Loading │ │ ├── Loading.mdx │ │ ├── Loading.stories.js │ │ └── index.js │ ├── Modal │ │ ├── Modal.mdx │ │ ├── Modal.stories.js │ │ └── index.js │ ├── Notification │ │ ├── Notification.mdx │ │ ├── Notification.stories.js │ │ └── index.js │ ├── Popover │ │ ├── Popover.mdx │ │ ├── Popover.stories.js │ │ └── index.js │ ├── ProgressBar │ │ ├── ProgressBar.mdx │ │ ├── ProgressBar.stories.js │ │ └── index.js │ ├── RadioButton │ │ ├── RadioButton.mdx │ │ ├── RadioButton.stories.js │ │ └── index.js │ ├── Range │ │ ├── Range.mdx │ │ ├── Range.stories.js │ │ └── index.js │ ├── Select │ │ ├── Select.mdx │ │ ├── Select.stories.js │ │ └── index.js │ ├── SideNav │ │ ├── NavItem.js │ │ ├── SideNav.mdx │ │ ├── SideNav.stories.js │ │ └── index.js │ ├── Sidebar │ │ ├── Sidebar.mdx │ │ ├── Sidebar.stories.js │ │ └── index.js │ ├── Spacer │ │ ├── Spacer.mdx │ │ ├── Spacer.stories.js │ │ └── index.js │ ├── StatusDot │ │ ├── StatusDot.mdx │ │ ├── StatusDot.stories.js │ │ └── index.js │ ├── StyledLink │ │ ├── StyledLink.mdx │ │ ├── StyledLink.stories.js │ │ └── index.js │ ├── Table │ │ ├── Table.stories.js │ │ ├── const.js │ │ ├── getExpandColumnConfig.js │ │ ├── index.js │ │ └── muiStyleOverrides.js │ ├── Tabs │ │ ├── Tabs.mdx │ │ ├── Tabs.stories.js │ │ └── index.js │ ├── TabsAlt │ │ ├── TabsAlt.mdx │ │ ├── TabsAlt.stories.js │ │ └── index.js │ ├── Tag │ │ ├── Tag.mdx │ │ ├── Tag.stories.js │ │ └── index.js │ ├── TextArea │ │ ├── TextArea.mdx │ │ ├── TextArea.stories.js │ │ └── index.js │ ├── TextInput │ │ ├── TextInput.mdx │ │ ├── TextInput.stories.js │ │ └── index.js │ ├── Toggle │ │ ├── Toggle.mdx │ │ ├── Toggle.stories.js │ │ └── index.js │ ├── TreeNav │ │ ├── TreeNav.mdx │ │ ├── TreeNav.stories.js │ │ └── index.js │ └── Typography │ │ ├── Typography.mdx │ │ ├── Typography.stories.js │ │ └── index.js ├── hooks │ ├── isVisible.js │ ├── keepInView.js │ ├── keypress.js │ ├── useInputFocus.js │ └── usePrevious.js ├── index.js ├── interplayIndex.js ├── systemThemeCollapsed.js ├── systemtheme.js └── utils │ ├── floatingUiHelpers.js │ ├── selectUtil.js │ └── selectUtil.test.js ├── libs └── fortawesome-fontawesome-svg-core-1.3.0.tgz ├── package-lock.json ├── package.json ├── playroom.config.js ├── playroom ├── FrameComponent.js └── Snippets.js ├── public ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── images │ ├── orcaLogo.svg │ └── orchLogo.svg ├── index.html └── manifest.json ├── scripts ├── assume-role.js └── dev.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es": { 4 | "presets": [ 5 | ["@babel/preset-env", { "modules": false }], 6 | ["@babel/preset-react", { "runtime": "automatic" }] 7 | ] 8 | } 9 | }, 10 | "presets": [ 11 | "@babel/preset-env", 12 | ["@babel/preset-react", { "runtime": "automatic" }] 13 | ], 14 | "plugins": [ 15 | "@babel/plugin-transform-runtime", 16 | "@babel/plugin-proposal-class-properties", 17 | "babel-plugin-styled-components", 18 | "react-docgen" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | CONSUMERS= 2 | WORKING_DIR= 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "prettier", 4 | "prettier/react", 5 | "prettier/standard", 6 | "eslint:recommended", 7 | "plugin:react/recommended", 8 | "plugin:jest/recommended" 9 | ], 10 | "plugins": ["react", "jsx-a11y", "import", "prettier", "react-hooks", "jest"], 11 | "parserOptions": { 12 | "sourceType": "module", 13 | "ecmaVersion": 2020 14 | }, 15 | "env": { 16 | "browser": true, 17 | "es6": true 18 | }, 19 | "rules": { 20 | "prettier/prettier": "error", 21 | "react/prop-types": 1, 22 | "react/forbid-prop-types": 0, 23 | "react/display-name": 0, 24 | "react/jsx-filename-extension": 0, 25 | "react/jsx-boolean-value": 0, 26 | "react/jsx-props-no-spreading": 0, // TEMP, We really should fix this, it's done in so many places so will need time to refactor 27 | "import/first": 1, 28 | "import/prefer-default-export": 1, 29 | "import/no-named-as-default": 0, 30 | "react/require-default-props": 0, 31 | "react/no-typos": 1, 32 | "react-hooks/rules-of-hooks": "error", 33 | "react-hooks/exhaustive-deps": "warn", 34 | "no-nested-ternary": 0, // TEMP, We really should fix this, it's done in so many places so will need time to refactor 35 | "no-useless-rename": 0, // TEMP, react-scripts using latest eslint which is buggy: https://github.com/eslint/eslint/issues/12335 36 | "no-return-assign": 0, 37 | "no-restricted-globals": 0, 38 | "no-underscore-dangle": 0, // graphql __typename is valid case 39 | "jsx-curly-brace-presence": 0, // TEMP, getting a property substring of undefined error when lint runs, 40 | "react/jsx-key": "warn" 41 | }, 42 | "settings": { 43 | "react": { 44 | "version": "detect" 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## What this PR does, and why 2 | 3 | > Add an explanation of what the code in this PR does. Add screenshot/screencapture and jira link where necessary. 4 | -------------------------------------------------------------------------------- /.github/workflows/chromatic.yml: -------------------------------------------------------------------------------- 1 | name: Run Chromatic on Storybook 2 | on: push 3 | 4 | jobs: 5 | chromatic-deployment: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Use Node.js 20 9 | uses: actions/setup-node@v3 10 | with: 11 | node-version: 20.12.2 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | - name: Install dependencies 17 | run: | 18 | npm ci --loglevel verbose 19 | - name: Publish to Chromatic 20 | uses: chromaui/action@v1 21 | with: 22 | projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} 23 | onlyChanged: true 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: orca:npm:ci 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | pull-requests: write 14 | actions: write 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Use Node.js 20 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: 20.12.2 21 | - name: npm install, build, and test 22 | run: | 23 | npm ci 24 | npm run lint 25 | npm run dist 26 | env: 27 | HUSKY_SKIP_INSTALL: 1 28 | CI: true 29 | - name: run security audit of npm packages 30 | run: | 31 | npm run audit-ci 32 | - name: run security check on code 33 | id: code_security_scan 34 | run: | 35 | pip install --upgrade njsscan 36 | njsscan . 37 | - name: scan for exposed aws secrets 38 | run: | 39 | git clone https://github.com/awslabs/git-secrets.git 40 | cd ./git-secrets 41 | sudo make install 42 | cd ../ 43 | rm -rf git-secrets 44 | git secrets --register-aws 45 | git-secrets --scan -r 46 | - name: "Publish version of package to NPM registry" 47 | uses: JS-DevTools/npm-publish@v1 48 | id: publish 49 | with: 50 | token: ${{ secrets.NPM_TOKEN }} 51 | check-version: true 52 | - name: Create a Release 53 | if: steps.publish.outputs.type != 'none' 54 | id: create_release 55 | uses: actions/create-release@v1 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 | with: 59 | tag_name: ${{ steps.publish.outputs.version }} 60 | release_name: Release ${{ steps.publish.outputs.version }} 61 | body: Automated release message to be implemented. 62 | draft: false 63 | prerelease: false 64 | -------------------------------------------------------------------------------- /.github/workflows/closeStalePR.yml: -------------------------------------------------------------------------------- 1 | name: 'Close stale issues and PRs' 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | permissions: 7 | issues: write 8 | pull-requests: write 9 | actions: write 10 | 11 | jobs: 12 | stale: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/stale@v9 16 | with: 17 | stale-issue-message: 'Issue will be closed due to inactivity. Please comment if you would like to keep it open.' 18 | stale-pr-message: 'PR will be closed due to inactivity. Please comment if you would like to keep it open.' 19 | days-before-stale: 30 20 | operations-per-run: 100 -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request Checks 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - "master" 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Use Node.js 20 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: 20.12.2 18 | - name: npm install, build, and test 19 | run: | 20 | npm ci 21 | npm run lint 22 | npm run test 23 | env: 24 | HUSKY_SKIP_INSTALL: 1 25 | CI: true 26 | - name: run security audit of npm packages 27 | run: | 28 | npm run audit-ci 29 | - name: run security check on code 30 | id: code_security_scan 31 | run: | 32 | pip install --upgrade njsscan 33 | njsscan . 34 | - name: scan for exposed aws secrets 35 | run: | 36 | git clone https://github.com/awslabs/git-secrets.git 37 | cd ./git-secrets 38 | sudo make install 39 | cd ../ 40 | rm -rf git-secrets 41 | git secrets --register-aws 42 | git-secrets --scan -r 43 | env: 44 | CI: true 45 | -------------------------------------------------------------------------------- /.github/workflows/storybook.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Storybook to github page 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy-storybook: 10 | # needs: build 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | pull-requests: write 15 | actions: write 16 | steps: 17 | - uses: actions/checkout@v2 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: 20.12.2 21 | registry-url: https://registry.npmjs.org/ 22 | - name: npm install and deploy 23 | run: | 24 | npm ci 25 | npm run deploy-storybook -- --ci 26 | env: 27 | CI: true 28 | GH_TOKEN: github-orchestrated:${{ secrets.GITHUB_TOKEN }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /build 8 | /demo 9 | 10 | # testing 11 | /coverage 12 | 13 | # misc 14 | .DS_Store 15 | .env.local 16 | .env.development.local 17 | .env.test.local 18 | .env.production.local 19 | .idea 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | # serverless 26 | .serverless/ 27 | /dist 28 | /es 29 | 30 | # interplay 31 | /interplay/*/ 32 | 33 | .build_storybook 34 | 35 | .env -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # dependencies 2 | /node_modules 3 | 4 | # testing 5 | /coverage 6 | 7 | # misc 8 | .DS_Store 9 | 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Development folders and files 15 | scripts 16 | config 17 | 18 | # serverless 19 | .serverless/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "none" 3 | } 4 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ["../lib/**/*.@(mdx|stories.@(js))"], 3 | 4 | addons: [ 5 | "@storybook/addon-docs", 6 | "@storybook/addon-links", 7 | "@storybook/addon-viewport", 8 | "@storybook/addon-a11y", 9 | "@storybook/addon-toolbars", 10 | "@storybook/components", 11 | "@storybook/manager-api", 12 | "@storybook/core-events", 13 | "@chromatic-com/storybook", 14 | "@storybook/preset-create-react-app", 15 | "@storybook/addon-webpack5-compiler-babel" 16 | ], 17 | 18 | framework: { 19 | name: "@storybook/react-webpack5", 20 | options: {} 21 | }, 22 | 23 | swc: () => ({ 24 | jsc: { 25 | transform: { 26 | react: { 27 | runtime: "automatic" 28 | } 29 | } 30 | } 31 | }) 32 | }; 33 | -------------------------------------------------------------------------------- /.storybook/manager-head.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.storybook/manager.js: -------------------------------------------------------------------------------- 1 | import { addons } from "@storybook/manager-api"; 2 | import orcsTheme from "./orcsTheme"; 3 | import { STORY_RENDERED } from "@storybook/core-events"; 4 | 5 | addons.register("TitleAddon", (api) => { 6 | const customTitle = "ORCS Design System by TeamForm"; // Define your customTitle title 7 | let interval = null; 8 | const setTitle = () => { 9 | clearTimeout(interval); 10 | let storyData = null; 11 | try { 12 | storyData = api.getCurrentStoryData(); // Some time get error 13 | } catch (e) {} 14 | let title; 15 | if (!storyData) { 16 | title = customTitle; 17 | } else { 18 | title = `${storyData.kind} - ${storyData.name} ⋅ ${customTitle}`; 19 | } 20 | if (document.title !== title) { 21 | // As few dom operations as possible 22 | document.title = title; 23 | } 24 | interval = setTimeout(setTitle, 100); 25 | }; 26 | setTitle(); 27 | api.on(STORY_RENDERED, (story) => { 28 | setTitle(); 29 | }); 30 | }); 31 | 32 | addons.setConfig({ 33 | sidebarAnimations: true, 34 | theme: orcsTheme, 35 | showPanel: true, 36 | panelPosition: "bottom" 37 | }); 38 | -------------------------------------------------------------------------------- /.storybook/orcsTheme.js: -------------------------------------------------------------------------------- 1 | import { create } from "@storybook/theming/create"; 2 | import { colors } from "../lib/systemtheme"; 3 | 4 | export default create({ 5 | base: "light", 6 | brandTitle: "Orcs Design System", 7 | brandUrl: "https://orchestrated-io.github.io/orcs-design-system", 8 | brandImage: 9 | "https://uploads-ssl.webflow.com/5f4852427e784b4cada3e0d0/60f7c55ecbc1d945a25c93ec_logo__orcsdesignsystem.png", 10 | brandTarget: "_self", 11 | colorPrimary: colors.primary, 12 | colorSecondary: colors.primaryDark, 13 | 14 | // UI 15 | appBg: colors.greyLightest, 16 | appContentBg: colors.white, 17 | appPreviewBg: colors.white, 18 | appBorderColor: colors.primary, 19 | appBorderRadius: 4, 20 | 21 | // Typography 22 | fontBase: 23 | '"Open Sans", -apple-system, BlinkMacSystemFont, Roboto, sans-serif', 24 | fontCode: "monospace", 25 | 26 | // Text colors 27 | textColor: colors.black, 28 | textInverseColor: colors.white, 29 | 30 | // Toolbar default and active colors 31 | barTextColor: colors.white, 32 | barSelectedColor: colors.primaryDarkest, 33 | barBg: colors.primary, 34 | 35 | // Form colors 36 | inputBg: "white", 37 | inputBorder: "silver", 38 | inputTextColor: "black", 39 | inputBorderRadius: 4 40 | }); 41 | -------------------------------------------------------------------------------- /.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.storybook/static/CNAME: -------------------------------------------------------------------------------- 1 | styleguide.orchestrated.io -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Orchestrated Systems Pty Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /__mocks__/@fortawesome/react-fontawesome.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | /** 3 | * Mocks @fortawesome/react-fontawesome.js to return a simple, empty element 4 | * with the correct class name for the given `icon` prop. We use this to keep full 5 | * content out of our rendered component tests. 6 | */ 7 | import React from "react"; 8 | import PropTypes from "prop-types"; 9 | 10 | FontAwesomeIcon.propTypes = { 11 | icon: PropTypes.oneOfType([ 12 | PropTypes.object, 13 | PropTypes.array, 14 | PropTypes.string 15 | ]), 16 | className: PropTypes.string 17 | }; 18 | 19 | export function FontAwesomeIcon(props) { 20 | const { icon, className } = props; 21 | const classNames = ["svg-inline--fa"]; 22 | 23 | if (className) { 24 | classNames.push(className); 25 | } 26 | 27 | if (typeof icon === "string") { 28 | classNames.push(icon); 29 | } else { 30 | classNames.push(`fa-${icon.iconName}`); 31 | } 32 | 33 | return ; 34 | } 35 | -------------------------------------------------------------------------------- /__mocks__/fileMock.js: -------------------------------------------------------------------------------- 1 | module.exports = "test-file-stub"; 2 | -------------------------------------------------------------------------------- /__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; -------------------------------------------------------------------------------- /audit-ci-strict.json: -------------------------------------------------------------------------------- 1 | { 2 | "low" : true, 3 | "reporttype": "full", 4 | "report": true 5 | } 6 | -------------------------------------------------------------------------------- /audit-ci.json: -------------------------------------------------------------------------------- 1 | { 2 | "high": true, 3 | "skipDev": true, 4 | "allowlist": [] 5 | } 6 | -------------------------------------------------------------------------------- /config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return "module.exports = {};"; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return "cssTransform"; 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | const path = require("path"); 4 | 5 | // This is a custom Jest transformer turning file imports into filenames. 6 | // http://facebook.github.io/jest/docs/tutorial-webpack.html 7 | 8 | module.exports = { 9 | process(src, filename) { 10 | return `module.exports = ${JSON.stringify(path.basename(filename))};`; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /interplay/interplay.json: -------------------------------------------------------------------------------- 1 | { 2 | "teamId": "ck0ronzww000002s6cht86oyw", 3 | "projectId": "sAsdXnTMxO", 4 | "framework": "react", 5 | "examplePaths": [ 6 | "lib/components/*/*.stories.js", 7 | "lib/components/Typography/Typography.stories.mdx" 8 | ], 9 | "includePaths": [], 10 | "deployPaths": [], 11 | "packages": [ 12 | { 13 | "ignore": ["systemtheme", "styleLink", "getOptionByValue"], 14 | "name": "orcs-design-system", 15 | "relativePath": "package.json", 16 | "src": { 17 | "entry": "lib/interplayIndex.js" 18 | } 19 | } 20 | ], 21 | "exampleMatchers": [ 22 | { 23 | "include": "**/*.stories.js", 24 | "matchPatterns": ["{componentName}/", ".*/{componentName}."], 25 | "matchProperty": "relativePath" 26 | }, 27 | { 28 | "include": "lib/components/Typography/Typography.stories.mdx", 29 | "matchPatterns": ["H1|H2|H3|H4|H5|H6|P|Text|Code|Quote"], 30 | "matchProperty": "name" 31 | } 32 | ], 33 | "nestedExampleLimit": 1, 34 | "peerDependencies": { 35 | "styled-components": "^5.2.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/Colour.mdx: -------------------------------------------------------------------------------- 1 | import { 2 | Meta, 3 | ColorPalette, 4 | ColorItem, 5 | Story, 6 | Canvas 7 | } from "@storybook/addon-docs"; 8 | import { colors } from "./systemtheme"; 9 | import Flex from "./components/Flex"; 10 | import Colour from "./assets/Colour"; 11 | import Box from "./components/Box/"; 12 | import * as ColourStories from "./assets/Colour/Colour.stories"; 13 | 14 | 15 | 16 | # Colour 17 | 18 | These are the colours used throughout the design system, defined in `systemtheme`. They can be referenced using the `color` prop for components that accept this prop, or through referencing the theme object. 19 | 20 | ## Main palette 21 | 22 | 23 | 38 | 51 | 64 | 77 | 90 | 103 | 104 | 105 | ## Monochrome opacities 106 | 107 | For black and white colours at different opacities, use the following scales. 108 | 109 | ### Black opacity scale 110 | 111 | 112 | 113 | ### White opacity scale 114 | 115 | 116 | 117 | ## Coloured opacities 118 | 119 | ### Primary opacity scale 120 | 121 | 122 | 123 | ### Secondary opacity scale 124 | 125 | 126 | 127 | ### Success opacity scale 128 | 129 | 130 | 131 | ### Warning opacity scale 132 | 133 | 134 | 135 | ### Danger opacity scale 136 | 137 | 138 | -------------------------------------------------------------------------------- /lib/GlobalStyles.js: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from "styled-components"; 2 | import { themeGet } from "@styled-system/theme-get"; 3 | // GLOBAL STYLES 4 | // For browser reset, setting global box sizing and font sizing etc. 5 | 6 | const GlobalStyles = createGlobalStyle` 7 | /* apply a natural box layout model to all elements, but allowing components to change */ 8 | html { 9 | box-sizing: border-box; 10 | line-height: 1.15; 11 | line-height: calc(2px + 2ex + 2px); 12 | } 13 | html * { 14 | line-height: calc(2px + 2ex + 2px); 15 | } 16 | *, *:before, *:after { 17 | box-sizing: inherit; 18 | } 19 | html, 20 | body { 21 | height: 100%; 22 | width: 100%; 23 | margin: ${(props) => themeGet("space.0")(props)}; 24 | } 25 | body { 26 | font-family: ${(props) => themeGet("fonts.main")(props)}; 27 | color: ${(props) => themeGet("colors.greyDarkest")(props)}; 28 | } 29 | /* set rem text size and styling */ 30 | html { font-size: 62.5%; } 31 | body { 32 | font-size: ${(props) => 33 | themeGet("fontSizes.2")( 34 | props 35 | )}; // equivalent to 16px (or 14px with collapsed theme) because of % change to html font size above 36 | } 37 | main { 38 | display: flex; 39 | align-items: stretch; 40 | align-content: stretch; 41 | width: 100%; 42 | } 43 | section { 44 | height: ${(props) => themeGet("appScale.navBarSize")(props)}; 45 | width: 100%; 46 | overflow-y: scroll; 47 | } 48 | img { 49 | border-style: none; 50 | } 51 | small { 52 | font-size: 80%; 53 | } 54 | p { 55 | margin: ${(props) => themeGet("space.0")(props)}; 56 | } 57 | h1, h2, h3, h4, h5, h6 { 58 | font-weight: ${(props) => themeGet("fontWeights.1")(props)}; 59 | font-family: ${(props) => themeGet("fonts.main")(props)}; 60 | margin: ${(props) => themeGet("space.0")(props)}; 61 | } 62 | h1 { 63 | font-size: ${(props) => themeGet("fontSizes.6")(props)} 64 | } 65 | h2 { 66 | font-size: ${(props) => themeGet("fontSizes.5")(props)} 67 | } 68 | h3 { 69 | font-size: ${(props) => themeGet("fontSizes.4")(props)} 70 | } 71 | h4 { 72 | font-size: ${(props) => themeGet("fontSizes.3")(props)} 73 | } 74 | h5 { 75 | font-size: ${(props) => themeGet("fontSizes.2")(props)} 76 | } 77 | h6 { 78 | font-size: ${(props) => themeGet("fontSizes.1")(props)} 79 | } 80 | a, 81 | p, 82 | small, 83 | li, 84 | h1, 85 | h2, 86 | h3, 87 | h4, 88 | h5, 89 | h6 { 90 | word-break: break-word; 91 | } 92 | `; 93 | 94 | export default GlobalStyles; 95 | -------------------------------------------------------------------------------- /lib/Spacing.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Canvas } from "@storybook/blocks"; 2 | 3 | 4 | 5 | # Spacing 6 | 7 | This design system uses a range of scales to define the space around and within components, as well as their sizes. These scales are part of the design system's theme (default: `systemtheme`) and can be utilized as values for [Styled System](https://styled-system.com/)-style props. Most components come with wrappers that can access Styled System's `space` and `layout` props. 8 | 9 | ## Space Scale 10 | 11 | The **space** scale defines the spacing values. For ease of reference, t-shirt sizing aliases have been added. For example, `p="r"`, `p="4"`, and `p={4}` are all valid and equivalent. 12 | 13 | Our default spacing is `r`, which stands for "regular". 14 | 15 | | **Array Index** | **T-shirt Size** | **Value** | 16 | | --------------- | ---------------- | --------- | 17 | | 0 | - | 0 | 18 | | 1 | xxs | 2px | 19 | | 2 | xs | 4px | 20 | | 3 | s | 8px | 21 | | 4 | r | 16px | 22 | | 5 | l | 24px | 23 | | 6 | xl | 32px | 24 | | 7 | xxl | 64px | 25 | | 8 | xxxl | 128px | 26 | 27 | ## Sizes Scale 28 | 29 | The **sizes** scale operates similarly to the space scale, providing consistent sizing values for components. 30 | 31 | ## Spacer Component 32 | 33 | To define uniform space between elements, such as controlling the spacing between `Button` components within a `Flex` row, use the `Spacer` component. For more details and examples, refer to the [Spacer component documentation](./?path=/docs/components-spacer--margin). 34 | -------------------------------------------------------------------------------- /lib/SystemThemeProvider.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import { ThemeProvider } from "styled-components"; 4 | import { default as GlobalStyles } from "./GlobalStyles"; 5 | import systemtheme from "./systemtheme"; 6 | 7 | const SystemThemeProvider = ({ children }) => { 8 | return ( 9 | 10 | <> 11 | 12 | {children} 13 | 14 | 15 | ); 16 | }; 17 | 18 | SystemThemeProvider.propTypes = { 19 | children: PropTypes.node 20 | }; 21 | 22 | export default SystemThemeProvider; 23 | -------------------------------------------------------------------------------- /lib/assets/Colour/Colour.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { Colour } from "."; 4 | import Flex from "../../components/Flex"; 5 | import Box from "../../components/Box"; 6 | 7 | export default { 8 | title: "System/Colour" // Title of your story section 9 | }; 10 | 11 | export const BlackOpacityScale = () => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | 26 | export const WhiteOpacityScale = () => ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ); 42 | 43 | export const PrimaryOpacityScale = { 44 | render: () => ( 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | ), 58 | name: "Primary Opacity Scale" 59 | }; 60 | 61 | export const SecondaryOpacityScale = { 62 | render: () => ( 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | ), 76 | name: "Secondary Opacity Scale" 77 | }; 78 | 79 | export const SuccessOpacityScale = () => ( 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | ); 93 | 94 | export const WarningOpacityScale = () => ( 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | ); 108 | 109 | export const DangerOpacityScale = () => ( 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ); 123 | -------------------------------------------------------------------------------- /lib/assets/Colour/index.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { themeGet } from "@styled-system/theme-get"; 3 | import shouldForwardProp from "@styled-system/should-forward-prop"; 4 | import { css } from "styled-components"; 5 | 6 | export const Colour = styled("div").withConfig({ shouldForwardProp })( 7 | (props) => { 8 | return css({ 9 | backgroundColor: themeGet(`colors.${props.bg}`)(props), 10 | width: "75px", 11 | height: "75px" 12 | }); 13 | } 14 | ); 15 | 16 | /** @component */ 17 | export default Colour; 18 | -------------------------------------------------------------------------------- /lib/assets/Images/orcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/orchestrated-io/orcs-design-system/897d1e90587f52f7c1ac46feb9f9f12c66576e2f/lib/assets/Images/orcs.png -------------------------------------------------------------------------------- /lib/components.test.js: -------------------------------------------------------------------------------- 1 | import * as components from "."; 2 | 3 | test("all components exported", () => { 4 | expect(Object.keys(components)).toMatchInlineSnapshot(` 5 | Array [ 6 | "ActionsMenu", 7 | "ActionsMenuBody", 8 | "ActionsMenuHeading", 9 | "ActionsMenuItem", 10 | "Avatar", 11 | "Badge", 12 | "Box", 13 | "Button", 14 | "ButtonGroupContainer", 15 | "ButtonGroupItem", 16 | "ButtonLink", 17 | "Card", 18 | "Checkbox", 19 | "Code", 20 | "DatePicker", 21 | "Divider", 22 | "Expandable", 23 | "Flex", 24 | "FlexItem", 25 | "FloatingPanels", 26 | "GlobalStyles", 27 | "Grid", 28 | "GridItem", 29 | "H1", 30 | "H2", 31 | "H3", 32 | "H4", 33 | "H5", 34 | "H6", 35 | "Header", 36 | "HeaderComplex", 37 | "HeaderSimple", 38 | "Icon", 39 | "Loading", 40 | "Modal", 41 | "Notification", 42 | "P", 43 | "Popover", 44 | "ProgressBar", 45 | "Quote", 46 | "RadioButton", 47 | "Range", 48 | "Select", 49 | "SideNav", 50 | "Sidebar", 51 | "SidebarClose", 52 | "SidebarPanel", 53 | "SidebarPanels", 54 | "SidebarTab", 55 | "SidebarTabs", 56 | "Small", 57 | "Spacer", 58 | "StatusDot", 59 | "StyledLink", 60 | "SystemThemeProvider", 61 | "Table", 62 | "Tabs", 63 | "TabsAlt", 64 | "Tag", 65 | "Text", 66 | "TextArea", 67 | "TextInput", 68 | "Toggle", 69 | "TreeNav", 70 | "Typography", 71 | "VARIANT_COLORS", 72 | "getOptionByValue", 73 | "styleLink", 74 | "systemThemeCollapsed", 75 | "systemtheme", 76 | ] 77 | `); 78 | }); 79 | -------------------------------------------------------------------------------- /lib/components/ActionsMenu/ActionsMenu.animations.js: -------------------------------------------------------------------------------- 1 | import { keyframes } from "styled-components"; 2 | 3 | export const crossFadeIn = keyframes` 4 | 0% { 5 | opacity: 0; 6 | } 7 | 75% { 8 | opacity: 0; 9 | } 10 | 100% { 11 | opacity: 1; 12 | } 13 | `; 14 | 15 | export const beforeDotCollapsing = keyframes` 16 | 0% { 17 | transform: translate(0, -6px); 18 | } 19 | 50% { 20 | transform: translate(0, 0); 21 | } 22 | 100% { 23 | transform: translate(0, 0); 24 | } 25 | `; 26 | 27 | export const beforeDotExpanding = keyframes` 28 | 0% { 29 | transform: translate(0, 0); 30 | } 31 | 50% { 32 | transform: translate(0, 0); 33 | } 34 | 100% { 35 | transform: translate(0, -6px); 36 | } 37 | `; 38 | 39 | export const afterDotCollapsing = keyframes` 40 | 0% { 41 | transform: translate(0, 6px); 42 | } 43 | 50% { 44 | transform: translate(0, 0); 45 | } 46 | 100% { 47 | transform: translate(0, 0); 48 | } 49 | `; 50 | 51 | export const afterDotExpanding = keyframes` 52 | 0% { 53 | transform: translate(0, 0); 54 | } 55 | 50% { 56 | transform: translate(0, 0); 57 | } 58 | 100% { 59 | transform: translate(0, 6px); 60 | } 61 | `; 62 | 63 | export const beforeCrossExpanding = keyframes` 64 | 0% { 65 | height: 4px; 66 | transform: rotate(-45deg); 67 | } 68 | 50% { 69 | height: 4px; 70 | transform: rotate(-45deg); 71 | } 72 | 100% { 73 | height: 18px; 74 | transform: translate(0, -7px) rotate(-45deg); 75 | } 76 | `; 77 | 78 | export const beforeCrossCollapsing = keyframes` 79 | 0% { 80 | height: 18px; 81 | transform: translate(0, -7px) rotate(-45deg); 82 | } 83 | 50% { 84 | height: 4px; 85 | transform: rotate(-45deg); 86 | } 87 | 100% { 88 | height: 4px; 89 | transform: rotate(-45deg); 90 | } 91 | `; 92 | 93 | export const afterCrossExpanding = keyframes` 94 | 0% { 95 | height: 4px; 96 | transform: rotate(45deg); 97 | } 98 | 50% { 99 | height: 4px; 100 | transform: rotate(45deg); 101 | } 102 | 100% { 103 | height: 18px; 104 | transform: translate(0, -7px) rotate(45deg); 105 | } 106 | `; 107 | 108 | export const afterCrossCollapsing = keyframes` 109 | 0% { 110 | height: 18px; 111 | transform: translate(0, -7px) rotate(45deg); 112 | } 113 | 50% { 114 | height: 4px; 115 | transform: rotate(45deg); 116 | } 117 | 100% { 118 | height: 4px; 119 | transform: rotate(45deg); 120 | } 121 | `; 122 | -------------------------------------------------------------------------------- /lib/components/ActionsMenu/ActionsMenu.mdx: -------------------------------------------------------------------------------- 1 | import { Story, Controls, Meta, Canvas } from "@storybook/addon-docs"; 2 | import ActionsMenu from "."; 3 | import * as stories from "./ActionsMenu.stories"; 4 | 5 | 6 | 7 | # Actions Menu 8 | 9 | [Default actions menu](#default-actions-menu) | [Left offset actions menu](#left-offset-actions-menu) | [Advanced actions menu](#advanced-actions-menu) | [Custom actions menu](#custom-actions-menu) | [Text button actions menu](#text-button-actions-menu) | [Properties](#properties) 10 | 11 | This component should be used when an item in the UI has multiple actions that can be taken on it. 12 | 13 | The child components `ActionsMenuItem` are rendered either as a react router link ``, standard html hyperlink ``, or button ` 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | basicFlex.storyName = "Basic Flex"; 21 | -------------------------------------------------------------------------------- /lib/components/Flex/FlexItem.mdx: -------------------------------------------------------------------------------- 1 | import { Story, Meta, Canvas, Controls } from "@storybook/addon-docs"; 2 | import { FlexItem } from "."; 3 | import Button from "../Button"; 4 | import Icon from "../Icon"; 5 | import * as stories from "./FlexItem.stories"; 6 | 7 | 8 | 9 | # FlexItem 10 | 11 | [Properties](#properties) | [Examples](#examples) | [Upgrading](#upgrading) 12 | 13 | To use `FlexItem` to control the spacing between children of `Flex` you must also import it: 14 | `import { FlexItem } from "orca-design-system"`. 15 | 16 | ### Using `FlexItem` 17 | 18 | You don't necessarily need to use `` as the direct child element to `` unless you need to apply specific `flexbox` properties to the item. In most cases, once you set the desired properties on `` it will layout the child elements as intended, whether these be `` or any other component like `` or even standard HTML like a `
` or ``. However, if you want to use the flex-specific CSS properties for items within the container, like `flex` or `align-self`, you will need to use `FlexItem` to apply these properties. 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/components/Flex/FlexItem.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FlexItem } from "."; 3 | import Button from "../Button"; 4 | import Icon from "../Icon"; 5 | 6 | export default { 7 | title: "Components/FlexItem", 8 | component: FlexItem 9 | }; 10 | 11 | export const basicFlexItem = () => ( 12 | 13 | 17 | 18 | ); 19 | 20 | basicFlexItem.storyName = "Basic Flex Item"; 21 | -------------------------------------------------------------------------------- /lib/components/Flex/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import styled, { ThemeProvider } from "styled-components"; 4 | import { 5 | space, 6 | layout, 7 | flexbox, 8 | color, 9 | border, 10 | position, 11 | compose 12 | } from "styled-system"; 13 | import { css } from "@styled-system/css"; 14 | import shouldForwardProp from "@styled-system/should-forward-prop"; 15 | import styledPropTypes from "@styled-system/prop-types"; 16 | 17 | const FlexStyles = compose(space, layout, flexbox, color, border, position); 18 | 19 | const FlexWrapper = styled("div") 20 | .withConfig({ 21 | shouldForwardProp 22 | }) 23 | .attrs((props) => ({ 24 | "data-testid": props.dataTestId 25 | ? props.dataTestId 26 | : props["data-testid"] 27 | ? props["data-testid"] 28 | : null 29 | }))((props) => css({ boxSizing: "border-box", gap: props.gap }), FlexStyles); 30 | 31 | const FlexItem = styled("div")( 32 | css({ 33 | boxSizing: "border-box" 34 | }), 35 | FlexStyles 36 | ); 37 | 38 | export default function Flex({ children, gap, theme, ...props }) { 39 | const component = ( 40 | 41 | {children} 42 | 43 | ); 44 | 45 | if (theme) { 46 | return ( 47 | 48 | {children} 49 | 50 | ); 51 | } 52 | return theme ? ( 53 | {component} 54 | ) : ( 55 | component 56 | ); 57 | } 58 | 59 | Flex.propTypes = { 60 | /** Children of `Flex` are taken as node elements */ 61 | children: PropTypes.node, 62 | gap: PropTypes.string, 63 | theme: PropTypes.object, 64 | ...styledPropTypes.space, 65 | ...styledPropTypes.layout, 66 | ...styledPropTypes.flexbox 67 | }; 68 | 69 | Flex.defaultProps = { 70 | display: "flex", 71 | flexDirection: "row", 72 | flexWrap: "nowrap", 73 | justifyContent: "flex-start", 74 | alignItems: "stretch" 75 | }; 76 | 77 | export { FlexItem }; 78 | -------------------------------------------------------------------------------- /lib/components/FloatingPanels/FloatingPanels.mdx: -------------------------------------------------------------------------------- 1 | import { Story, Canvas, Controls, Meta } from "@storybook/addon-docs"; 2 | import FloatingPanels from "."; 3 | import * as stories from "./FloatingPanels.stories"; 4 | 5 | 6 | 7 | # Floating Panels 8 | 9 | The Floating Panels Component is a flexible React component that can be used in two different ways. 10 | 11 | 1. Creates a set of collapsible panels floating on the screen. It's ideal for displaying information or controls that need to be easily accessible but not always visible. 12 | 2. Can be used as a control panel for actions, where instead of a set of collapsible panels, it's a single panel with a set of actions. 13 | 14 | ## Features 15 | 16 | - Customisable container height 17 | - Customisable position on the screen 18 | - Expandable/collapsible panels 19 | - Configurable icons and titles for each panel 20 | - Can chose panel to expand on initial load 21 | - Ability to include any content within panels (can pass content as a component) 22 | 23 | ## Floating Panels with content 24 | 25 | Panels that include `content` are inherently selectable and will display their content when selected. 26 | 27 | 28 | 29 | ## Floating Panels as a buttons 30 | 31 | Panels without `content` are inherently unselectable. Include `onClick` to respond to clicks. 32 | 33 | 34 | 35 | ## Aligning Floating Panels 36 | 37 | You can align panels and their content to the left, right, or center of the parent container. 38 | 39 | 40 | 41 | ## Lock panel selection 42 | 43 | Include `disablePanelSelection={true}` to prevent selection changes. Useful while a panel is doing async work (such as performing an API query). 44 | 45 | 46 | 47 | ## Force panel highlight 48 | 49 | Include `forceHighlight={true}` to make panels appear selected. Useful for mutually exclusive mode selection. 50 | 51 | Note: This should be replaced with a proper mode select solution. 52 | 53 | 54 | 55 | ## Divided panels 56 | 57 | Include `grouping={"any"}` to generate dividers between different groupings of panels. 58 | 59 | 60 | 61 | ## Properties 62 | 63 | 64 | -------------------------------------------------------------------------------- /lib/components/FloatingPanels/Panel.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import PropTypes from "prop-types"; 3 | 4 | import Icon from "../Icon"; 5 | import Popover from "../Popover"; 6 | import { 7 | PanelWrapper, 8 | PanelHeader, 9 | HeaderContent, 10 | Title, 11 | PanelContent, 12 | IconButton 13 | } from "./FloatingPanels.styles"; 14 | 15 | export const Panel = ({ 16 | iconName, 17 | title, 18 | containerHeight, 19 | content, 20 | isExpanded, 21 | toggleExpanded 22 | }) => { 23 | const [isHovered, setIsHovered] = useState(false); 24 | 25 | if (!content) { 26 | return null; 27 | } 28 | 29 | return ( 30 | 31 | setIsHovered(true)} 34 | onMouseLeave={() => setIsHovered(false)} 35 | onFocus={() => setIsHovered(true)} 36 | onBlur={() => setIsHovered(false)} 37 | > 38 | 39 | 40 | {isExpanded && {title}} 41 | 42 | {isExpanded && ( 43 | 44 | 49 | 50 | )} 51 | 52 | {content} 53 | 54 | ); 55 | }; 56 | 57 | Panel.propTypes = { 58 | title: PropTypes.string.isRequired, 59 | iconName: PropTypes.string.isRequired, 60 | content: PropTypes.node.isRequired, 61 | containerHeight: PropTypes.string, 62 | isExpanded: PropTypes.bool.isRequired, 63 | toggleExpanded: PropTypes.func.isRequired 64 | }; 65 | 66 | export const PanelBarIcon = ({ 67 | iconName, 68 | title, 69 | toggleExpanded, 70 | isExpanded, 71 | forceHighlight 72 | }) => { 73 | return ( 74 | 75 | 81 | 82 | 83 | 84 | ); 85 | }; 86 | 87 | PanelBarIcon.propTypes = { 88 | iconName: PropTypes.string.isRequired, 89 | title: PropTypes.string.isRequired, 90 | toggleExpanded: PropTypes.func.isRequired, 91 | isExpanded: PropTypes.bool.isRequired, 92 | forceHighlight: PropTypes.bool.isRequired 93 | }; 94 | -------------------------------------------------------------------------------- /lib/components/Grid/Grid.mdx: -------------------------------------------------------------------------------- 1 | import { Meta, Story, Canvas, Controls } from "@storybook/addon-docs"; 2 | import Grid, { GridItem } from "."; 3 | import Button from "../Button"; 4 | import * as stories from "./Grid.stories"; 5 | 6 | 7 | 8 | # Grid 9 | 10 | [Properties](#properties) | [Examples](#examples) | [Upgrading](#upgrading) 11 | 12 | Grid component using the built-in Styled System Grid Layout through its `grid` function. Use `Grid` to display layouts that must conform to a specific grid structure (columns and/or rows), or for tabular data and contents. If no grid structure is needed, for example in a horizontal row of buttons, use `Flex` instead. 13 | 14 | Importing `GridItem` is recommended for use with `Grid` to retain sizing for the children; see [example](#without-griditem-vs-with-griditem) below. 15 | 16 | 17 | 18 | ## Properties 19 | 20 | This component uses Styled System props. `Grid` uses `space`, `layout`, `color` and `grid` props. `Grid` uses `space`, `layout`, and `color` props. 21 | 22 | ### For reference, see: 23 | 24 | - [space on Styled-System](https://styled-system.com/table#space) 25 | - [layout on Styled-System](https://styled-system.com/table#layout) 26 | - [color on Styled-System](https://styled-system.com/table#color) 27 | - [grid on Styled-System](https://styled-system.com/table#space) 28 | - [CSS Grid Properties](https://css-tricks.com/snippets/css/complete-guide-grid) 29 | - [systemtheme.js](https://github.com/orchestrated-io/orcs-design-system/blob/master/packages/orcs-design-system/lib/systemtheme.js) (our arrays and scales for design system values) 30 | 31 | By default, we've set certain default values on `Grid` as documented in the table below. 32 | 33 | 34 | 35 | ## Examples 36 | 37 | ### With Colours 38 | 39 | 40 | 41 | ### Template Columns and Rows 42 | 43 | 44 | 45 | ### Width-based Columns and Rows 46 | 47 | 48 | 49 | ### Using `GridItem` 50 | 51 | Using `GridItem` to wrap individual children in the grid ensures that the children retain their original dimensions, as not using `GridItem` allows children to take up the full width of their grid cell. This does not affect the behaviour of text content. 52 | 53 | #### With `GridItem` 54 | 55 | Note that `GridItem` has default `padding="r"` where `r` refers to the **r**egular alias in the [space array scale](https://github.com/orchestrated-io/orcs-design-system/blob/master/packages/orcs-design-system/lib/systemtheme.js). 56 | 57 | 58 | 59 | 60 | 61 | #### Without `GridItem` 62 | 63 | 64 | 65 | ## Upgrading 66 | 67 | This component is a **breaking change** from the [previous version](https://www.npmjs.com/package/styled-grid-component) of `Grid`. Use the following table as a guide to convert from `styled-grid-component` properties to `styled-system` props. 68 | 69 | | **styled-grid-component** | **styled-system** | 70 | | ------------------------- | --------------------- | 71 | | `width` | `width` | 72 | | `height` | `height` | 73 | | `templateColumns` | `gridTemplateColumns` | 74 | | `templateRows` | `gridTemplateRows` | 75 | | `rowGap` | `gridRowGap` | 76 | | `autoRows` | `gridAutoRows` | 77 | -------------------------------------------------------------------------------- /lib/components/Grid/Grid.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Grid, { GridItem } from "../Grid"; 3 | import Button from "../Button"; 4 | 5 | export default { 6 | title: "Components/Grid", 7 | component: Grid 8 | }; 9 | 10 | export const basicGrid = () => ( 11 | 12 | 1 13 | 2 14 | 3 15 | 4 16 | 5 17 | 6 18 | 19 | ); 20 | basicGrid.storyName = "Default Grid"; 21 | 22 | export const backgroundColourGrid = () => ( 23 | 24 | 1 25 | 26 | 2 27 | 28 | 3 29 | 4 30 | 5 31 | 6 32 | 33 | ); 34 | backgroundColourGrid.storyName = "With background colours"; 35 | 36 | export const templateColumnsAndRows = () => ( 37 | 42 | 43 | This Grid uses repeat and fr to specify the grid structure. 44 | 45 | Fusce sit amet lorem lectus. 46 | Nullam lobortis porta iaculis. 47 | Pellentesque fermentum elementum elit non blandit. 48 | Etiam rhoncus ultricies lorem nec imperdiet. 49 | Pellentesque. 50 | 51 | ); 52 | templateColumnsAndRows.storyName = "Template columns and rows"; 53 | 54 | export const widthColumnsAndRows = () => ( 55 | 60 | 61 | This Grid uses widths and percentages to specify the grid structure. 62 | 63 | Fusce sit amet lorem lectus. 64 | Nullam lobortis porta iaculis. 65 | Pellentesque fermentum elementum elit non blandit. 66 | Etiam rhoncus ultricies lorem nec imperdiet. 67 | Pellentesque. 68 | 69 | Each GridItem goes down the columns first and then goes through the rows. 70 | 71 | 72 | To change this, change the value of the gridAutoFlow property. The default 73 | value is columns. 74 | 75 | 76 | ); 77 | widthColumnsAndRows.storyName = "Width-based columns and rows"; 78 | 79 | export const withGridItem = () => ( 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |

Text-only item

92 |
93 |
94 | ); 95 | withGridItem.storyName = "With GridItem"; 96 | 97 | export const textWithGridItem = () => ( 98 | 99 | 3 100 | 1 101 | 4 102 | 1 103 | 5 104 | 9 105 | 106 | ); 107 | textWithGridItem.storyName = "Text with GridItem"; 108 | 109 | export const withoutGridItem = () => ( 110 | 111 | 112 | 113 | 114 |

Text-only item

115 |
116 | ); 117 | withoutGridItem.storyName = "Without GridItem"; 118 | -------------------------------------------------------------------------------- /lib/components/Grid/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled, { ThemeProvider } from "styled-components"; 3 | import { grid, space, layout, flex, color, compose } from "styled-system"; 4 | import { css } from "@styled-system/css"; 5 | import shouldForwardProp from "@styled-system/should-forward-prop"; 6 | import PropTypes from "prop-types"; 7 | 8 | const GridStyles = compose(space, layout, grid, flex, color); 9 | 10 | const GridWrapper = styled("div") 11 | .withConfig({ shouldForwardProp }) 12 | .attrs((props) => ({ 13 | "data-testid": props.dataTestId 14 | ? props.dataTestId 15 | : props["data-testid"] 16 | ? props["data-testid"] 17 | : null 18 | }))( 19 | css({ 20 | boxSizing: "border-box", 21 | display: "grid" 22 | }), 23 | GridStyles 24 | ); 25 | 26 | const GridItem = styled("div") 27 | .withConfig({ shouldForwardProp }) 28 | .attrs((props) => ({ 29 | "data-testid": props.dataTestId 30 | ? props.dataTestId 31 | : props["data-testid"] 32 | ? props["data-testid"] 33 | : null 34 | }))( 35 | css({ 36 | boxSizing: "border-box", 37 | minWidth: "0" 38 | }), 39 | GridStyles 40 | ); 41 | 42 | export default function Grid({ children, theme, ...props }) { 43 | const component = {children}; 44 | return theme ? ( 45 | {component} 46 | ) : ( 47 | component 48 | ); 49 | } 50 | 51 | Grid.propTypes = { 52 | /** Children of `Grid` are taken as node elements */ 53 | children: PropTypes.node, 54 | /** Auto flow direction and rules */ 55 | gridAutoFlow: PropTypes.oneOf([ 56 | "row", 57 | "column", 58 | "row dense", 59 | "column dense", 60 | "inherit", 61 | "initial", 62 | "unset" 63 | ]), 64 | /** Defines the spacings between columns and rows. Takes the nth value, or a specific alias, from the design system spacing scale (specified in theme). */ 65 | gridGap: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), 66 | /** Specifies the system design theme. */ 67 | theme: PropTypes.object 68 | }; 69 | 70 | Grid.defaultProps = { 71 | gridAutoFlow: "row", 72 | gridGap: "0" 73 | }; 74 | 75 | GridItem.defaultProps = { 76 | padding: "0" 77 | }; 78 | 79 | export { GridItem }; 80 | -------------------------------------------------------------------------------- /lib/components/Header/Header.mdx: -------------------------------------------------------------------------------- 1 | import { Story, Meta, Canvas, Controls } from "@storybook/addon-docs"; 2 | import Header from "."; 3 | import * as stories from "./Header.stories"; 4 | 5 | 6 | 7 | # Header 8 | 9 | Header component for app layout. Supports app name, username and avatar as props. 10 | 11 | ## Default Header 12 | 13 | 14 | 15 | ## Properties 16 | 17 | 18 | -------------------------------------------------------------------------------- /lib/components/Header/Header.stories.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Header from "."; 3 | import TextInput from "../TextInput"; 4 | import Box from "../Box"; 5 | import Flex from "../Flex"; 6 | import { Small } from "../Typography"; 7 | import Toggle from "../Toggle"; 8 | import Divider from "../Divider"; 9 | import Icon from "../Icon"; 10 | 11 | export default { 12 | title: "Components/Header", 13 | component: Header, 14 | decorators: [ 15 | (storyFn) => ( 16 | 17 | {storyFn()} 18 | 19 | ) 20 | ] 21 | }; 22 | 23 | const dummyLogo = ( 24 | 31 | 37 | 38 | ); 39 | 40 | const UserMenuContent = () => { 41 | const [checked, setChecked] = React.useState(false); 42 | 43 | const handleToggleChange = () => { 44 | setChecked(!checked); 45 | }; 46 | 47 | return ( 48 | <> 49 | 50 | Compact theme 51 | 52 | 58 | 59 | 60 | 61 | Logout 62 | 63 | 64 | ); 65 | }; 66 | 67 | export const defaultHeader = () => ( 68 |