Giter VIP home page Giter VIP logo

headstorm / foundry-ui Goto Github PK

View Code? Open in Web Editor NEW
16.0 5.0 43.0 19.03 MB

Foundry-UI is a React UI Library built which prioritizes theming, accessibility, and performance. Fully typed with TypeScript, animated by react-spring, themed with styled-components, and made accessible by polished and jest-axe.

License: Apache License 2.0

JavaScript 1.36% TypeScript 23.90% HTML 74.38% CSS 0.36%
react ui-components ui-kit accessibility a11y a11y-react

foundry-ui's Introduction

Foundry UI
The only open-source UI library that's made to be remade

Intro

Foundry-UI (or Foundry for short) is a great choice for your next software project's user interface (UI), because Foundry was created to:

  • Support enterprise applications at any stage, from proof-of-concept to launch to enhancements
  • Allow custom styling and behavior of individual components with Foundry’s unique architecture
  • Reach users on any device for any use case while maintaining full functionality and accessibility

At of the time this writing, Foundry is new and launching with a fully supported React version. The Angular version is a work in progress, but don't let that stop you from reaching out about contributing on the Angular version.

NPM npm npm bundle size (scoped) license a11y

Foundry UI CI/CD Coverage Branches Coverage Functions Coverage Lines Coverage Statements

Foundry UI is lovingly developed by Headstorm's Open Source group. Please reach out to us at: [email protected]

Getting Started

Requirements

  • Node >= 10.18

Peer dependencies:

  • react ^16.13.1
  • react-dom ^16.13.1
  • react-is ^16.13.1
  • @react-spring/web ^9.2.0
  • styled-components >= 5.1.0

If you're new to React or web development, no problem! There are other great open-source tools out there that will have you creating gleaming web apps in a reasonably short amount of time. If you haven't already, set up a new React project--a great place to start is create-react-app. Storybook is the open source tool we use to demonstrate and document the Foundry UI components. Click the Live Demo link above to view the Foundry components now or checkout the Contributing section below for information about how to run Storybook on your local machine.

Install Foundry-UI into a React app

Foundry for React is available as a scoped public Node package. You can use npm or yarn to add the Foundry package to your project. From you project's root directory, where the package.json file is located, run the command:

npm install @headstorm/foundry-react-ui
// or
yarn add @headstorm/foundry-react-ui

For the peer dependency styled components, react-is, and react-spring install from the same root directory, run the command:

npm install --save styled-components react-is @react-spring/web
// or
yarn add styled-components react-is @react-spring/web

Usage

Hello World

Get started with a simple hello world

import { Card } from '@headstorm/foundry-react-ui';

function HelloWorld() {
    return <Card>Hello World!</Card>;
}
export default HelloWorld;

Output:

hello world

In this hello world example, you can see the Card component has preset styling for the Container and Body components that come right out of the box. Foundry components are wrapped in a container element. See the CardContainer and Body base configurations below. It is recommended that you check out the component's source code to see what styles are included.

// /foundry-react-ui/src/components/Card/Card.tsx

export const CardContainer = styled(StyledBaseDiv)`
  ${({ elevation }: { elevation: number }) => {
    const { grayXlight, background, shadow } = useColors();
    return `
      display: inline-flex;
      flex-flow: column nowrap;
      font-size: 1rem;
      border-radius: 0.25rem;
      border: ${!elevation ? `1px solid ${grayXlight}` : '0px solid transparent'};
      transition: box-shadow ${timings.slow}, filter ${timings.slow}, border ${timings.slow};
      ${getShadowStyle(elevation, shadow)}
      background-color: ${background};
  `;
  }}
`;

...

export const Body = styled(StyledBaseDiv)`
  ${() => {
    const { grayMedium } = useColors();
    return `
      padding: 1.5rem 1.5rem;
      color: ${grayMedium};
    `;
  }}
`;

Override styles

import React from 'react';
import { Card, colors } from '@headstorm/foundry-react-ui';
import styled from 'styled-components';

// Foundry provides a basic set of colors, but feel free to add your own
const myColors = {
  ...colors,
  blue: 'blue',
  };

// We recommend starting with the Foundry provided subcomponent, in this case 'Card.Container',
// and then add your own overrides or new styles.
// If you were to set ThemedContainer = styled.div, you would lose all the Foundry preset styling.

const ThemedContainer = styled(Card.Container)`
  border-bottom: 1rem solid ${myColors.blue};
  border-radius: 1rem;
  overflow: hidden;
  margin: 2rem;
`;

const StyledHeader = styled(Card.Header)`
  background-color: ${myColors.blue};
  color: white;
  font-size: 5rem;
  padding: 1rem;
`;

const ThemedBody = styled(Card.Body)`
  color: ${myColors.grayMedium};
  font-family: Comic Sans MS, cursive, sans-serif;
  font-size: 4rem;
  font-weight: bold;
  padding: 2rem 1rem;
  text-align: center;
`;

function HelloWorld() {
    return (
      <Card
        StyledContainer={ThemedContainer} // Set your overrides for each element
        StyledHeader={StyledHeader}
        StyledBody={ThemedBody}
        header={'HELLO'} // Add your content
      >
        World
    </Card>);
};
export default HelloWorld;

Output:

hello world overrides

Composing components

See the Form demo example and source code

Global Styling / Provider

FoundryProvider provides global styling utilities and the option to store constants globally by setting styleConstants.

See the Global styling demo example and Global styling source code

Analytics

Events triggered on Foundry Components can be tracked using a custom analytics function passed to the Foundry Provider. See the Analytics event action examples and Analytics example source code

Contributing

Pick a ticket from the Priority to do swim-lane of the project board. Fork and clone the repository and create a branch for your ticket, with the ticket number prefixing the name of the ticket (i.e. 4-publish-package-to-npm). When making commits, be sure to prefix your commit messages with the ticket number, like so: #4 Updating package.json to make the package public. Once you've made a commit it should automatically be moved to the In progress swim-lane, and then moved to Needs review once a PR is made. For commits to be included in the changelog you muse use formatted commit messages. We've made this easier to do by adding a script for committing messages, simply use npm run commit or yarn commit to create your commits that should be added to the changelog.

Locally

Run yarn install to install the dependencies, then you can run yarn start to start the storybook server. The app will automatically reload if you change any of the source files.

Running unit tests

Run yarn test to execute the unit tests via Jest.

Theming components

HS-UI is themeable on many levels and allows you to customize as little or as much as you want. Gone are the days of having to use deep CSS selectors with !important on every style.

Basics

Each base component is built from at least one styled-component. When theming each component, it is highly recommended that you open the source for the base component so that you know all of the styles currently applied.

For example, the Card component has 4 (at the time of writing) styled-components which make up the entire component. It has a container, header, body, and footer. There are many levels of customization you can apply to the Card:

  • Color scheme, animation timings, and other constants
    • Completely replace the colors and timings constants objects, so that existing styled-components will use your theme without any other intervention.
    • Import the built-in constants, spread them at the top of your new constants object, and then override only the constants you want to change.
    • NOTE: This feature has not yet been completed, see Issue #15 to follow the progress.
  • Replace a portion of a base component with your own styled-component
    • While the Card Header is a styled.div with text-transform: uppercase, you can pass in any styled component to replace the header entirely, it could even be a styled.span if you want! Create your styled-component and then pass it to the StyledHeader prop of the Card and voilà! It doesn't use any of the previous styles that were originally created for the Card Header.
    • You'll have access to all the props which are passed to the styled-component as well. In the case of Card, the elevation prop is passed directly into the Container, so while a Material Design theme may use it to programmatically control the box-shadow and border property, you can use it for anything you wish.
  • Add CSS/SASS overrides to a portion of a base component
    • This almost the same as the previous method, except that you'll first import the piece you're overriding from the original base component. In the case of the Card Header, you'll import Card, { Header } from 'foundry-react-ui/Card;, and then use that as your base as so: styled(Header)`styles go here`. You'll have the full power of styled-components, and you can include your constants files as you like.
    • Again, the styled(Header) will receive the same props that the original did, giving you full control of how to handle the props in the style.

Notes on architecture

We use custom HTML elements in place of the built in styled-components elements. These elements have a set of sensible default styles that we wish to apply to all elements. This means:

// don't do this
import styled from 'styled-components';

const MyContainer = styled.div`styles`;

// do this
import styled from 'styled-components';
import { StyledBaseDiv } from '@headstorm/foundry-react-ui';

const MyContainer = styled(StyledBaseDiv)`styles here`;

Passing Refs to Children Elements

Each Foundry component is made up of numerous child components and DOM elements. Most of the time, awareness of this internal structure is not necessary, but there are a few occasions when it is necessary to reference these DOM nodes directly outside of the typical dataflow. See the React Docs for more info

Although, each Foundry component is a little different, you will find that most have a container element that holds all additional DOM elements. The convention you will notice is there is an API to customize each major sub-component, their props, and access to their ref. For example, Card accepts props for StyledContainer, containerProps, and containerRef; StyledHeader, headerProps, and headerRef; StyledBody, bodyProps, and bodyRef; and StyledFooter, footerProps, and footerRef; among others.

You might be wondering, 'Why don't I just pass a "ref" property along with the sub-component's Props?" And, this in fact would work...most of the time. However, there are some internal "ref"-ing that goes on behind the scenes and at those occurrences passing the ref inside the sub-component props would not work. For example, if you want to reference the Card's container element, create a ref, perhaps with React.createRef(), and pass that ref to the containerRef prop, not through the containerProps as {ref: myRef}.

Since all the Foundry components are functional components, it was determined that refForwarding wasn't necessary and wouldn't be supported. So, don't pass a "ref" prop to a Foundry component because it won't be forwarded. Instead, simply create a ref and explicitly pass it to the sub-component you want to target using the supported API props.

Creating new components

Enabling Theming

Theming is enabled through props of each component. When building a new component, or adding a styled-component to an existing component, ensure that there is a matching prop to accept an override, and that styled-component is a named export from the component. See the Card component as an example.

State of CICD workflow

What's working?

  • Pushes to master trigger a release build
  • Auto versioning
  • Pushes to v1-release trigger a pre-release build build checks on every PR to master and v1-release
  • Change logs are generated (see link below)
  • storybook docs are generated and checked in for releases
  • Test coverage

How am I impacted as a developer?

  • Husky has been added for pre-commit and pre-push hooks. Please pull the latest and install dependencies in /foundry-ui to get the hooks working. (the root install will also update dependencies, but using npm instead of yarn - we can fix this in the future for consistency)
  • Commits that we want added to the Change log must use commitizen, when working inside of foundry-react-ui using yarn commit will use commitizen. Alternatively you can use npx git-cz
  • Commits to be excluded from the change log (eg. "Fix typo that broke my pre commit linting") can continue to use normal git commits
  • Package.json is no longer the source of the version published, semantic-release uses git tags to determine the release version - this is only the case in our workflows. If we do a manual push we must update package.json before publishing
  • Auto versioning - No more package.json version bumps required 🎉

foundry-ui's People

Contributors

adrikakhan avatar agheadstorm avatar avilebroker avatar blakekrammes avatar chloetedder avatar cnkeats avatar dawsonbooth avatar dependabot[bot] avatar donaldjbrady avatar enyiasonye avatar ericbaumann avatar garrettrathke avatar griseldazbalmaceda avatar harrisonnoble avatar ishaanbhagwat avatar j-leidy avatar j-storey5 avatar jakeoien avatar jjrockhill avatar joien1 avatar jonesdebu avatar marras0914 avatar meghanainaganti avatar patrickdevries avatar rfisher58 avatar semantic-release-bot avatar vlineros-hs avatar willwinman avatar wmangimelli avatar xavierdonnellon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

foundry-ui's Issues

Dropdown

  • Implement base UI
  • Fully themable
  • Add story with meaningful knobs
  • Add figma frame to story
  • A11y compliance
  • Unit/snapshot testing

API:

  • values
  • options
  • multi
  • onInputChange
  • onSelect
  • clearable
  • onClear

Suggested sub-components

  • ValueContainer
  • ValueItem
  • OptionsContainer
  • OptionItem

Ensure storybook is not included in the installed bundle

Currently it is being included in consuming apps' node_modules

AC:

  • ensure it is not included in consuming apps' node_modules

From @jakeoien:

This ticket was intending to solve an issue where linking Foundry in a local project causes multiple versions of React to load. We came up with this as the solution. Turns out, this isn’t enough - we’re still seeing the issue even after this change. The problem we’re running into is that these storybook dependencies are a part of the foundry package itself.

I’m wondering if a better way of going about this would be to move all of the storybook stuff out of our src/ directory so that it’s not actually a part of our bundled code.

The big thing this blocks is trying to make changes like bugfixes using a local version of foundry, that currently won’t work.

From me:

I’ve seen packages (@react-three/drei for instance) that put all the storybook stuff in .storybook - which may solve the issue for us.

Update storybook images to display correctly in github pages

We are currently using an image in the /public folder which doesn’t work when hosted on github pages. We should instead host one to foundry-ui.com and use that instead on storybook.

AC

  • Upload new image to be hosted on foundry-ui.com (@aVileBroker to provide image and upload to S3)
  • Update storybook image path to the new hosted url

Centralized color scheme

Add the Headstorm brand colors to a centralized file which can be exported and used with hs-ui, as well as imported from the library by external projects.

ScrollArea component

See examples of how custom scrollbars can be created using JS to detect the scrollable area available, as well as the current scroll position to achieve custom scrollbars.

https://twitter.com/sebastienlorber/status/1516847672992350211
https://medium.com/headstorm/in-search-of-a-better-scroll-ux-pattern-3a22d4cff5f1

The default behavior should be a simple scrollbar that is similar to OSX scrollbars. (floating, expand/appear when hovered near gutter)

We should use standard terminology from HTML scrollbar styling, like thumb, gutter, handle, etc.

Add an optional scroll progress indicator subcomponent that shows the current scroll progress

Fix a11y add-on

Perhaps because of styled-components, the a11y add-on for storybook doesn't work as it does with the angular version of hs-ui.

A cursory google search didn't find any explanation, so there could be another issue.

AC:

  • The a11y add-on should be functioning and show passing/failing accessibility tests

Investigate SSR support

When using Foundry with server-side rendering (SSR) apps, i.e. apps created with NextJS, don't have a window object and will require polyfilling.

AC:

  • Test out Foundry UI in a NextJS application
  • Find a solution to get it working (Google is your friend)

Add a CSS in JS system

Take a base component and abstract one or more styles to a separate file for reuse using a CSS in JS system.

It will lay the groundwork for abstract sizing (small, medium, large), as well as consistent baselines, colorschemes, etc. This will also make the library smarter by powering the styling engine with TypeScript, make it more DRY, and more generally more consistent.

Dropdown | Virtualize options list for better performance of long lists

For long lists of options, we - and material ui - are quite inefficient at rendering them, causing long lists to be very slow/janky in opening and scrolling.

Virtualizing the options list and passing each option its current status (in view vs not in view) would be very powerful. We can roll our own intersection observer hook to achieve this, or use a package - but building our own would be the least risky approach imo.

AC:

  • As an option scrolls out of view, it should be replaced with an div of the height it originally was (or another performant alternative, feel free to do some research on best practices. It would be bad if it ends up being worse on performance than doing nothing)

Divider

  • Implement base UI
  • Fully themable
  • Add story with meaningful knobs
  • Add figma frame to story
  • A11y compliance
  • Unit/snapshot testing

Built on the native hr element. Can be fancy with an svg shape or simple, or have multiple exports/versions controlled the API. I'll leave this open ended to see if someone wants to get creative with it.

Sub-components:

  • Line

API:

  • isShort

Table

  • Implement base UI
  • Fully themable
  • Add story with meaningful knobs
  • Add figma frame to story
  • A11y compliance
  • Unit/snapshot testing

Host storybook on foundryui.com

The benefits are keeping people on the main domain and allowing us to maintain docs for older versions (like v0, v1, v1.1, next, etc)

Button

  • Implement base UI
  • Fully themable
  • Add story with meaningful knobs
  • Add figma frame to story
  • A11y compliance
  • Unit/snapshot testing

Sub-components

  • Container
  • Icon
  • PointerFeedback
    • for hover effects, click effects, loading, etc.

API:

  • children
  • icon
  • type
  • isLoading
  • isProcessing

Fix module creation

Currently when running yarn build in the hs-react-ui folder, it creates a compiled-down version of the index.ts file but doesn't correctly compile the components and make them available as it should.

One possibility for this ticket is to start a brand new create-react-library and copy the components over to it, then replace hs-react-ui with that version. If you want to continue to try and trouble shoot the current environment, you can look at other libraries created with create-react-library to compare them.

Usage Recommendation Global Styling

For developers who are new to Foundry, create a Usage section in the package readme to describe the recommended usage of Foundry with global styling.

Publish package to npm

Once the project has an angular library, and an exportable component exists, publish the library package to npm. It should be importable by another project. (test with codesandbox.com or another quick-setup environment)

Getting access to or creating the npm organization will be a big first step.

Add functionality to allow replacing constants files

As a user of the UI library without much interest in CSS or styling (but who wants to change the color scheme), I want to be able to use a simple color scheme object like the one exported from hs-ui, but I don't want to have to replace every use of every color through a new styled prop. It's unnecessary and I hate styling and CSS.

AC:
Implement a method for replacing the files in the constants directory with custom ones.

SPIKE | Research theming architecture

From the original hs-ui pitch:
HS-UI is:
... opinionated in structure and approach, while remaining flexible in look and feel ...

In order to be able to import hs-ui/react/Button, and with a minimal amount of work, get a branded, customized look/feel, an architectural decision needs to be made.

It's also important to have a really nice looking default for developers who don't have ANY front-end theming understanding and are totally fine with just having headstorm orange all over their app.

The automated release is failing 🚨

🚨 The automated release from the master branch failed. 🚨

I recommend you give this issue a high priority, so other packages depending on you could benefit from your bug fixes and new features.

You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can resolve this 💪.

Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.

Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the master branch. You can also manually restart the failed CI job that runs semantic-release.

If you are not sure how to resolve this, here is some links that can help you:

If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.


Invalid npm token.

The npm token configured in the NPM_TOKEN environment variable must be a valid token allowing to publish to the registry https://registry.npmjs.org/.

If you are using Two-Factor Authentication, make configure the auth-only level is supported. semantic-release cannot publish with the default auth-and-writes level.

Please make sure to set the NPM_TOKEN environment variable in your CI with the exact value of the npm token.


Good luck with your project ✨

Your semantic-release bot 📦🚀

Dropdown | Add searching (with callbacks)

We should have a default internal search which sorts the current option list, which can be turned off and onChange callbacks (also pass the onDebouncedChange callback up as a separate function)

I like to use fuse.basic.js for fuzzy searching lists on client-side. It weights the results and allows for mispellings, searching multiple properties in a nested object, and weights for each property in nested objects. It also returns where in the strings the matches occur so that we can highlight/bold the letters which match the search.

The API could be

  • searchable
  • searchFiltersOptions (needs a better name - but this would be what tells us to filter the list ourselves, and add the boldness to the matched patterns)
  • onSearchChange
  • onDebouncedSearchChange

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.