GithubHelp home page GithubHelp logo

shopify / polaris-viz Goto Github PK

View Code? Open in Web Editor NEW
302.0 213.0 21.0 100.89 MB

A collection of React and React native components that compose Shopify's data visualization system

Home Page: https://polaris-viz.shopify.com

License: Other

JavaScript 3.56% TypeScript 88.71% SCSS 1.75% HTML 0.34% MDX 5.63%

polaris-viz's Introduction

Polaris viz

Polaris Viz is Shopify's data visualization system. It's what powers many of our data heavy experiences, including ShopifyQL Notebooks.

It is composed of two consumer-facing libraries:


  • polaris-viz version badge size badge

a collection of React components built for web


  • polaris-viz-native version badge size badge

    a collection of React Native components optimized for mobile experiences


Both libraries use the same Data Structure, Utility functions, Themes and SubComponents. All things shared between @shopify/polaris-viz and @shopify/polaris-viz-native are documented in the Storybook's Shared folder




Our libraries are structured to favor charts that prioritize accessibility and motion design. The goal is to help users create clear and meaningful analytics experiences.

We want to do the heavy lifting of developing charts, so our partners can focus on telling amazing data stories and not re-inventing the wheel.




Want to help us build the future of data viz? The system is currently in active development and we are working on expanding its features and available charts.

Pull requests are welcome! See the contribution docs for more information and to learn how to set up your development environment.




Source code is under a custom license based on MIT. The license restricts Polaris Viz usage to applications that integrate or interoperate with Shopify software or services, with additional restrictions for external, stand-alone applications.

polaris-viz's People

Contributors

envex avatar krystalcampioni avatar nickpresta avatar rita-morozova avatar philschoefer avatar dependabot[bot] avatar asmockler avatar susiekims avatar andrewzulaybar avatar thetrevorharmon avatar ksp2001 avatar acmertz avatar pbojinov avatar michaelnesen avatar blboyle avatar maryamkaka avatar lbwright avatar precillieo avatar mel-mel-king avatar kylekilbride avatar shopklaw avatar ericktamayo avatar shameelabd avatar ryanwilsonperkin avatar jimgraham avatar juwanpetty avatar maael avatar chrisdakin avatar michenly avatar nickpith avatar

Stargazers

Lyu Ji avatar Can Özmen avatar Tim Shnaider avatar Diogo Cardoso avatar Stanley Yang avatar João Fernandes avatar Emre DEĞER avatar Sören Martius avatar Moishi Netzer avatar  avatar  avatar Spark Cheng avatar Jordan Finneran avatar Charlie Trent avatar Teodoro Villanueva avatar Thomas Skjølberg avatar Maxim Postnikov avatar Keshav Khadka avatar Arman Hayrapetyan avatar Aleko Kvashilava avatar Majd Taweel avatar Ciphore avatar Drew Gillson avatar Stefan Ciprian Hotoleanu avatar tcosnr avatar Phillip avatar Tiago Lima avatar Jeffrey avatar Monir Abu Hilal avatar Doğukan Yıldız avatar Marcel Lee avatar Maximilian S avatar Jon Insley avatar Kristian Tasevski avatar Karl Leicht avatar Avishek Jana avatar Jason Le avatar Rodolfo avatar dnc avatar sicko avatar Muratva Stark avatar Stefano avatar 邓六石 avatar Geneviève Masioni avatar Wojciech Pasiński avatar Kenichi Saito avatar Mark McTamney avatar Sean Tu avatar  avatar David Gidwani avatar ibrahim ethem demirci avatar Joda Stößer avatar  avatar Kennedi avatar Vijay Solanki avatar Bart Stefanski avatar David avatar Thymo ter Doest avatar Michel Azevedo avatar Di Wu avatar LordSpace avatar Robert Herber avatar Haider Alshamma avatar Mingyang Li avatar  avatar  avatar Joel Van Horn avatar Eren Yüksel avatar  avatar Andrew Erdle avatar 码农朱哲 avatar Joshua Beach avatar halo avatar Guy Barnard avatar Erik Claesson avatar Alaattin Gökmen  avatar  avatar Hao Lee avatar Mike Wilson avatar Rihards Mantejs avatar Jay avatar  avatar Panagiotis Petridis avatar Matthew Fainman avatar Remy Wang avatar Cristian Rosu avatar Menachem Hornbacher avatar Bruno Wego avatar Chaolong avatar Sivakumar Kailasam avatar 大豆小淘 avatar  avatar ADITHYA THEJAS S avatar David Bird avatar kal avatar Tiago Danin avatar Jie Sheng avatar Mahmut Genc avatar Maksim Nikolaev avatar  avatar

Watchers

Shay avatar Lourens Naudé avatar Elvio Vicosa avatar Jeff Bruton avatar Adam Mark avatar Mai avatar Lucas Souza avatar Ryan Florence avatar Stella Miranda avatar Ben Doyle avatar Stephen Hunter avatar Luiz Adolpho avatar Bart Piotrowski avatar Shadab Rashid avatar Jeremy Morony avatar Dan Menard avatar Mark Ryan avatar Michael Nugent avatar Sebastian Skopp avatar Julia Winn avatar James Cloos avatar Misha Korablin avatar Thomas Conner avatar Stephen Hukish avatar Ryan Self avatar Karthik K N avatar Corwin Brown avatar Arpan Podduturi avatar João Júnior avatar Daniel Leroux avatar Alex Fi avatar Ahmad Alhour avatar Nik Ivanov avatar Tim Lombardo avatar Kaj Drobin avatar Paul Gagliardi avatar Annett Forcier avatar Satish Kanwar avatar Liz McDonald avatar Alejandro Gonzalez avatar Topher Bullock avatar Anita Mehrotra avatar  avatar Dave McVittie avatar Jared Rader avatar Robleh Jama avatar Nick Lee avatar Damyan Petkov avatar Julia Nguyen avatar Armando avatar Nicholas Simmons avatar Gil Greenberg avatar Kirsten Westeinde avatar  avatar Pauline Ramos avatar  avatar  avatar  avatar ryan avatar Ian Martin avatar Will Mowat avatar John Benson avatar Arbab Ahmed avatar Nick Bell avatar Derek Braid  avatar  avatar  avatar  avatar Anya Li avatar Tony Gaetani avatar Shashwat Singh avatar Sebastián Osorio avatar Bill Fienberg avatar Elijah McPherson avatar Katarina Batina avatar Ted Armstrong avatar Fatima Sajadi avatar Ian Donahue avatar Jeremy Ward avatar Alëna Iouguina avatar Yiğit Özkavcı avatar Christian Mackie avatar Fran avatar Robin Dykema avatar Scott Moorhouse avatar Preethi Krishnamoorthy Ramesh Kumar avatar  avatar Tidjane Tall avatar nicklepine avatar Joseph Kim avatar  avatar Keyvan K. avatar Robert Byrne avatar  avatar Fred Dawson avatar  avatar MesamH avatar  avatar Victor Daniel Catamo Rojas avatar Stephen Smyth avatar

polaris-viz's Issues

[Multi series bar chart] Replace the use of label in `get-stacked-values`, use another unique value

Currently, the use of label as a key in get-stacked-values does not work well for non-unique labels when creating the stacked values and the y-scale domain.

the issue lives in the call to the stack generator:

const barStack = stack()
    .offset(stackOffsetDiverging)
    .keys(series.map(({label}) => label));

example of what we don't handle, but would like to:

const data: Data[] = [
      data: [1, 2, 3], color: 'primary', label: 'oranges',
      data: [10, 20, 30], color: 'secondary', label: 'oranges',
]

[Line Chart][Feature request] Allow breaks in line chart when there is no data

The current Line Chart does not take into account the use case where there could be data points within the series that have no data. For example, in a time series line chart there could be days where no data is available.

There has been some exploration within the online store speed report time series graph to introduce a "break" within the line for days that do not have data.

image

Add Stacked bar chart to GroupedBarChart

The grouped bar chart currently supports the grouping of the bars but not stacking them.

In this issue, I will outline my thoughts on how to approach adding stacking to the current GroupedBarChart component.

Current design for stacking

Add helper utilities for mocking D3 in tests

We are heavily reliant on mocking D3 to facilitate testing. In order to reduce time spent on mocking D3 utilities and make it easier to test, I think we should write some test utilities. For example in src/components/StackedAreaChart/hooks/tests/use-y-scale.test.tsx, we have this:

jest.mock('d3-scale', () => ({
  scaleLinear: jest.fn(() => {
    const scale = (value: any) => value;
    scale.ticks = (numTicks: number) => Array.from(Array(numTicks));
    scale.range = (range: any) => (range ? scale : range);
    scale.domain = (domain: any) => (domain ? scale : domain);
    scale.nice = () => scale;
    return scale;
  }),
}));

but we have to overwrite this object later on in the tests, as we test for specific things:

const ticksSpy = jest.fn(() => [0, 25, 50]);
(scaleLinear as jest.Mock).mockImplementation(() => {
  const scale = (value: any) => value;
  scale.ticks = ticksSpy;
  scale.range = (range: any) => (range ? scale : range);
  scale.domain = (domain: any) => (domain ? scale : domain);
  scale.nice = () => scale;
  return scale;
});

I think having a scaleLinearMockHelper function could simplify testing utilities that use d3's scaleLinear.

Rename GroupedBarChart

Now that we have added the stacked orientation to the grouped bar chart, we should rename the component to something that reflects both orientations

Global SASS root path

From #112

If you plan to have lots of shared styles, you can set a global SASS root path. In the past I have added

SASS_PATH=src/styles/

to my node .env file and it would enable me to do something like @import 'common'. Maybe something to look at/try?

Fix esnext build relative paths

We keep having to check whether paths will work in web or not, since relative paths are not being built correctly.

Example of something that breaks (red) vs works (green):
Screen Shot 2021-04-29 at 6 11 46 PM

To test whether something works in web,

  • make your changes in Polaris Viz
  • dev up in web
  • run yarn build-consumer web in Polaris Viz
  • in web, start your server. If things are broken, you will get errors about imports not working/files not being found. If it works, dev should work as normal. Look at your component in question to confirm

Bar chart

Designs: https://www.figma.com/file/oAZvcYResB3Hccw0pqgGvK/Data-viz?node-id=214%3A0

Requirements:

  • Handles negatives
  • Can be displayed as a normal bar chart or histogram
  • Has tooltips
  • xAxis
  • properly detect the width of the yaxis strings
  • xAxis handling for long strings (probably also involves some height detection)
  • min bar height
  • Format data in tooltips
  • Animations
    • On hover

Polish:

  • maxwidth on tooltip (200px/160px for inner content)

  • fix tooltip spacing (too much margin on the right) + make tooltip a separate component

  • Ensure Tooltip does not cause overflow to the parent/page (means caring about the bounds for the xPosition)

  • histogram - does the label need to be aligned left?
    A real, good, histogram should have some features that are a bit of a departure from the bar chart. For example, it should really use a linear scale rather than the scaleband, to allow us to have a label on either side of each bar to indicate the range of the bucket. I experimented with what would be required for this and while it is probably possible with this component, I think it would just be better as a separate component if we see the demand. The experiment draft PR includes conditionally calling hooks, which obviously isn't an option. It also presents an issue of using our current data props to determine what a proper label would be when the data is histogram-style data. If you have ideas on how to make this work, I'd be happy to revisit it.
    All this being said, a histogram-like style can be achieved with our bar chart by removing the space between the bars and providing labels that indicate the range each label is displaying. I just think we should tone down the prop name so it doesn't shout "I'm a histogram" when really it is just a bit like a histogram. We can explain the nuances in the docs..

  • try to show max/min on yAxis (not a blocker)?

  • test on mobile: iOS, Android

  • test on browsers: Chrome, FF, Safari, Edge

  • fix spacing according to the design

  • fix small container height issue

  • write tests
    - [ ] make props consistent with linechart??

  • Update README and changelog!!!

Enhancements/future components:

  • Stacking
  • Grouped bar chart
  • Horizontal
  • different color for negative numbers?

Support Optional Chaining

While web supports optional chaining, this repo has jest errors whenever attempting to use the feature. I attempted to upgrade all the dependencies, but it wasn't a quick-fix to the solution, so we will need to spend a little bit of time digging into it. See #161 (comment) for more context.

X axis labels at edges get cut off

The first and last X axis labels will get cut off depending on their length. I have only used the line chart so I do not know if it happens on other charts. The last label is especially vulnerable to this.
Here is an example of it happening on both end:
labelcutoff-example
Seems like the svg doesn't account for the label length?

Add y-axis position option

There should be an option to position the y-axis on either the left side (current behavior) or right side of the chart.

Remove duplication of constants

Each component has a constants file and some of them have duplicates of each other. We should move these up to be shared across the repo

Improve environment

There are a couple code quality failings from our environment and some developer experience that could be improved. Some things that might help are:

  • Upgrade our TypeScript version
  • Update react-spring
  • Tweak tsconfig.json
    • Specifically, look into enabling skipLibCheck to speed things up quite a bit
  • Don't use sewing-kit for bundling, since it doesn't support libraries very well yet

LineChart and BarChart interface feedback

I did some exploration around implementing the LineChart and BarChart on the report viewer, and I had some feedback about the interfaces of the components. These are sort of just a first draft and meant to be the start of conversation.

1. Inconsistent data interfaces
I noticed that the Line chart's data interface looks like this:

data: {x: string, y: number}

Whereas the Bar chart's data interface looks like this:

data: {rawValue: number, label: string}

I found the Bar chart's interface to be more intuitive and informative, and I think we should use that interface in the line chart as well. While I realize that x and y are maybe more "pure" in terms of understanding the graph, there were questions I had when I was using it, like:

  • Which one is the label? which one is the value?
  • Is the value supposed to be formatted or not?
    Assuming that we want to make this easy to use for devs less familiar with working with viz, I think {rawValue: number, label: string} is a more intuitive interface.

2. Chart vs Tooltip formatters
There are places in report viewer where we display a different number on the tooltip as on the chart. For example, we use condense-number on the y-axis, but we display the full value on the chart tooltip. I think we ought to expose chart formatters and tooltip formatters for both axes. My thinking is that we have a series of fallbacks. So for a tooltip formatter, it would go formatTooltipValue -> formatChartValue -> rawValue. Then clients can choose to provide a formatter for those cases, or just let it fallback if the data is simpler.

3. Data formatting when values are interdependent
This one is a bit of a niche use case. If you choose a time grain of Month and have a range that includes multiple years, the chart formatter shows Jan 2019 for the first month, and then the rest of them it only shows the month (Feb, Mar, etc), until it becomes a new year, and it shows Jan 2020. This requires us to know about data points before and after the current datapoint.

The way I solved this in the report viewer was for the chart formatter to take an array of points instead of a single point, and format all of the datapoints on one go. It seems to me that this is too narrow of a use case to justify us doing something similar here.

My thinking for this was that we could have chartLabel and tooltipLabel, which would allow us to pass in the right values from the client and make the client handle cases like this.

Line chart tooltip feels intrusive on smaller charts.

This example is from the MarketingGlimpse. When the chart is condensed the tooltip tends to take over a good portion of the chart.

Carys had mentioned considering adding a max-width to the tooltip in cases where the chart is quite small.

Better Playground experience

Right now, the Playground is sort of a burden. It is hard to share code and we always end up committing it by accident. Instead of ignoring the Playground, I think we should "lean in" and make it more of a storybook experience where each component has a route where it can show some common behavior and a few interesting data sets

[Accessibility] Add tab events to data points

For a recent project with custom components we added tab events to each bar on a bar graph. Tabbing is considered a focus event and then triggered the tooltips. We should consider this for the library.

To implement the changes, we needed to add tabIndex={0} to each bar to make them tabbable, and an onFocus event handler to show the tooltip on focus.

An additional reason to do this is to bring our accessibility standards to the level of highcharts' accessibility module.

Import polaris-tokens scss globally

There are several scss files that include

@import 'node_modules/@shopify/polaris-tokens/dist/index';

Instead of having to add that in many places, we should define a global styles file that can include it for the entire project.

Per #29 (comment)

Empty data state

Empty data [] should not try to return a line chart, we should return null instead

Remove React and React DOM as depedencies

It would be better for our consumers if we could just list React and React DOM as peer and dev dependencies, rather than just dependencies. However, Sewing Kit currently requires both to be dependencies in order to run the playground.

Some options:

  • look into sewing kit's playground and see if we could allow it to use dev dependencies.
  • consider using something like Storybook instead for our Playground, which is what Polaris React does.

Stacked area chart

Add a stacked area chart that can replace the HighCharts one on the dashboard and be used in other cases as well

To do:

  • Determine offset
  • Fix chart reanimating on resize
  • Fix circular imports created in the first PR
  • Add docs

[MultiSeriesBarChart] Update tooltip to not cover the bar.

Reference:

After talking with @mirualves, it was decided that having the tooltip covering the bar was not ideal.

One option we were exploring was having the tooltip fall to the left or right of the bar depending on the position of the bar in the SVG.

Similar to the behaviour we see in the LineChart:

Highlight "current" series on interaction

There are two types of interactions where we may want to highlight one series and hide the others:

  • When hovering on an item in the legend, we may want to dim other items in the chart
    • Alternately, should clicking a legend item persist this behavior?
  • When hovering on the chart, when the mouse is on one line, we may want to dim the other lines

Designs:

image

Line Chart

Work done for this feature exists on branch line-chart-release; pre-release work should merge into that branch until we are ready for an official release of the line chart

Playground
import React, {useState} from 'react';
import {colorSky, colorSkyDark, colorBlue} from '@shopify/polaris-tokens';

import {LineChart} from '../src/components';

const formatMoney = new Intl.NumberFormat('en', {
  currency: 'USD',
  style: 'currency',
}).format;
const formatNumber = new Intl.NumberFormat('en').format;
const formatDate = new Intl.DateTimeFormat('en', {
  month: 'short',
  day: 'numeric',
}).format;

function generateData(numPoints, min = 5, max = 15) {
  return Array.from(Array(numPoints))
    .fill(null)
    .map((_, index) => {
      return {x: `${index}`, y: min + Math.floor(Math.random() * max)};
    });
}

const OVERVIEW_DASHBOARD_STYLE = [
  {name: 'Apr–Apr 30, 2020 was a good month', data: generateData(30)},
  {
    name: 'Mar 1–Mar 31, 2020',
    data: generateData(31),
    style: {
      color: 'colorSkyDark',
      lineStyle: 'dashed',
    },
  },
];

const LOTS_OF_DATA = [
  {
    data: [
      {x: '5', y: 100},
      {x: '6', y: -40},
      {x: '7', y: -20},
      {x: '8', y: -40},
      {x: '9', y: 250},
      {x: '10', y: 100},
      {x: '11', y: 100},
      {x: '12', y: -40},
      {x: '13', y: -20},
      {x: '14', y: -40},
      {x: '15', y: 250},
      {x: '16', y: 100},
    ],
    name: 'Data 1',
    style: {color: 'colorTeal'},
  },
  {
    data: generateData(8, 0, 1000),
    name: 'Data 2',
    style: {lineStyle: 'dashed'},
  },
  {
    data: generateData(10, 0, 1000),
    name: 'Data 3',
    style: {color: 'colorBlue'},
  },
  {
    data: generateData(8, 0, 1000),
    name: 'Data 4',
    style: {color: 'colorOrange', lineStyle: 'dashed'},
  },
];

export default function Playground() {
  const [dataSet, setDataSet] = useState('OVERVIEW_DASHBOARD');

  const series =
    dataSet === 'OVERVIEW_DASHBOARD' ? OVERVIEW_DASHBOARD_STYLE : LOTS_OF_DATA;

  function handleChangeDataSet() {
    setDataSet(
      dataSet === 'OVERVIEW_DASHBOARD' ? 'LOTS_OF_DATA' : 'OVERVIEW_DASHBOARD',
    );
  }

  return (
    <div
      style={{
        margin: '150px 0',
        fontFamily:
          "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
      }}
    >
      <div
        style={{
          maxWidth: 800,
          margin: 'auto',
          background: 'white',
          padding: 12,
          borderRadius: 6,
          border: `1px solid ${colorSky}`,
        }}
      >
        <LineChart
          xAxisLabels={series[0].data.map(({x}) =>
            formatDate(new Date(2020, 3, parseInt(x, 10) + 1)),
          )}
          formatYAxisValue={formatNumber}
          series={series}
        />

        <br />
        <hr style={{border: 0, height: 1, background: colorSkyDark}} />
        <br />

        <div style={{textAlign: 'left'}}>
          <button
            style={{
              border: `2px solid ${colorBlue}`,
              fontSize: 13,
              borderRadius: 8,
              color: colorBlue,
              padding: '7px 18px',
              fontWeight: 600,
              cursor: 'pointer',
              outline: 'none',
            }}
            onClick={() => handleChangeDataSet()}
          >
            Change data set
          </button>
        </div>
      </div>
    </div>
  );
}

Things to do

  • Render lines (#29)
  • X Axis (#29)
  • X Axis grid lines (#29)
  • Secondary (dashed) lines (#29)
  • Color lines (#29)
  • Y Axis (#29)
  • Y Axis grid lines (#29)
  • Crosshair on hover (#38)
  • Points on line on hover (#38)
  • Tooltips (#36)
  • Legend (#40)
  • Documentation (#44)
  • Once a baseline API/behavior is established, write tests (#46)

Bugs

  • Line stacking order
  • series.formatY is not being used to format series Y values (#45)
  • Tooltip may overflow page on right side of viz (reported in #45) (fixed in #48)
  • "Flash of unstyled content" on load (#50)
  • X-Axis has a key error when not enough labels are provided (#51)
  • DOMRect is not defined in old Edge versions (it uses ClientRect)

Enhancements

  • Share useWindowSize from Sparkline (#43)
  • Right-side Y-Axis (#41)
  • Accessibility? Add an accessibility label and role="image"? (#52)
  • Tweaks from Miru (#52)
    • I think we can use a lighter gray on the axis lines and the legend at the bottom could also be a bit lighter using the caption text color
    • We could keep the numbers on the x-axis aligned vertically in the middle with the axis line
    • Curious to know how if we have the flexibility to put fewer divisions on the y-axis

[RFC] Export subcomponents, utilities and hooks

Now we have some basic components in the repo, the idea of exporting some subcomponents, utilities and hooks has come up in discussions with @melissaluu, @asmockler, @philschoefer and @shameelabd. I've also discussed the idea with @mirualves.

On this issue, I am hoping to get a better idea of what would be helpful to export, and how we can still try to achieve consistency between components while enabling some one offs that don't belong in a reusable library. Please leave some examples of what would be helpful to your teams to export from this library that we aren't already exporting.

Display Datapoint information on GroupedBarChart tooltip

On the Grouped bar chart, when the labels are too long, every other label is omitted. In this case, we should show the label on the tooltip, so that a user can hover over a group of bars and be able to see the label for that group:

image (1)

[React Spring] Testing

Followup to #70 and more generally:
Find a way to run out the animation duration of React Spring to test before and after states

Create Polaris Viz logo

We need a logo for Polaris Viz. The logo should utilize similar colors that exist in Polaris Viz, and have a strong symbol that will work even at very small sizes (like a slack emoji).

Unify Data Interfaces

I did an audit of the data interfaces for the charts, and I found 5 different interfaces. I'm going to focus on 2 main ones.

Line Chart:

interface Series {
  label: string;
  data: {label: string, rawValue: number}[];
  color: Color;
  style?: Partial<{
    color: Color;
    lineStyle: LineStyle;
  }>;
}[]

type Labels = string[]

Multi Series Bar Chart, Stacked Area Chart:

interface Series {
  label: string;
  data: number[];
  color: Color;
}[]

type Labels = string[]

The two interfaces are similar, but the key distinction is that the latter requires the presence of the labels array. The first one could omit the labels. I propose that we unify the interfaces for the Line Chart, Multi Series Bar Chart, and Stacked Area Chart to the following interface:

interface Series {
  name: string;
  data: {label: string, rawValue: number}[];
  color?: Color;
  style?: LineStyle; // if applicable
}[]

Unifying the interfaces has several benefits:

  1. Consumers would have a consistent experience between multi-series charts.
  2. Consumers could prepare the data one way and swap the chart as needed (according to the volume of data).
  3. We could omit the required labels array and use the labels provided in series data array (we could expose a callback to the consumer if we need to give the consumer control of how we compute the labels. But it would be optional).

[Sparkine] Tweak area

Area should not have a solid opacity, but rather a gradient. Could be an option rather than a default

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.