Giter Club home page Giter Club logo

solid-styled's Introduction

solid-styled

Reactive stylesheets for SolidJS

NPM JavaScript Style Guide

Install

npm i solid-styled
npm i -D postcss
yarn add solid-styled
yarn add -D postcss
pnpm add solid-styled
pnpm add -D postcss

Features

  • Render stylesheets only once
  • Fine-grained reactive CSS properties
  • Scoped stylesheets
  • :global selector
  • @global at-rule
  • SSR
  • Near zero-runtime
  • <style jsx>

Examples

  • Vite - Open in CodeSandbox
  • Astro - Open in CodeSandbox

Usage

Integrations

css

Use the css tagged template for writing stylesheets.

import { css } from 'solid-styled';

function Title() {
  css`
    h1 {
      color: red;
    }
  `;

  return <h1>Hello World</h1>;
}

The template is also reactive. It works by replacing all templating values with a CSS variable. This allows the stylesheet to be only rendered once and can be shared by multiple components of the same scope.

import { css } from 'solid-styled';

function Button() {
  const [color, setColor] = createSignal('red');
  css`
    button {
      color: ${color()};
    }
  `;

  return (
    <button onClick={() => {
      setColor((c) => (c === 'red' ? 'blue' : 'red'));
    }}>
      Current color: {color()}
    </button>
  );
}

By default, all styles are scoped to its component and cannot leak into another component. The scoping only applies to all DOM nodes that can be found in the component, including the children of the external components.

import { css } from 'solid-styled';

function ForeignTitle() {
  return <h1>This is not affected</h1>;
}

function Title() {
  css`
    h1 {
      color: red;
    }
  `;

  return (
    <>
      <h1>This is affected.</h1>
      <ForeignTitle />
      <Container>
        <h1>This is also affected.</h1>
      </Container>
    </>
  )
}

:global

Since all selectors in a given stylesheet are scoped by default, you can use the :global pseudo selector to opt-out of scoping:

import { css } from 'solid-styled';

function Feed(props) {
  css`
    div > :global(* + *) {
      margin-top: 0.5rem;
    }
  `;

  return (
    <div>
      <For each={props.articles}>
        {(item) => (
          // This item is affected by the CSS of the Feed component.
          <FeedArticle data={item} />
        )}
      </For>
    </div>
  );
}

@global

You can use @global instead of :global if you want to declare multiple global styles

css`
  /* this is global */
  @global {
    body {
      background-color: black;
    }

    main {
      padding: 0.5rem;
    }
  }

  h1 {
    color: white;
  }
`;

Forward scope

Since solid-styled scopes DOM elements and not components by default, it doesn't affect things like <Dynamic>. Using use:solid-styled, we can forward the current scope/sheet to the component.

css`
  * {
    color: red;
  }
`;

<Dynamic component={props.as} use:solid-styled>
  {props.children}
</Dynamic>

which compiles into

useSolidStyled('xxxx', '*[s\\:xxxx]{color:red}');

<Dynamic component={props.as} s:xxxx style={vars()}>
  {props.children}
</Dynamic>

<style jsx>

Inspired by styled-jsx.

Use <style jsx> instead of css for declaring styles in JSX expressions. Both <style jsx> and css functions the same.

function Button() {
  const [color, setColor] = createSignal('red');
  return (
    <>
      <style jsx>
        {`
          button {
            color: ${color()};
          }
        `}
      </style>
      <button onClick={() => {
        setColor((c) => (c === 'red' ? 'blue' : 'red'));
      }}>
        Current color: {color()}
      </button>
    </>
  );
}

You can also use <style jsx global> for declaring global styles.

The main motivation for writing an alternative way of declaring styles with <style jsx> is to facilitate the migration from solid-styled-jsx to solid-styled. Possibly, some developers may as well use <style jsx> because of their familiarity with adding the styles inside the JSX.

SSR

<StyleRegistry>

For SSR, you can pass an array to the styles prop of <StyleRegistry>. This array collects all of the "critical" (initial render) stylesheets, that which you can render as a string with renderSheets.

import { renderSheets } from 'solid-styled';

const styles = [];

renderToString(() => (
  <StyleRegistry styles={styles}>
    <App />
  </StyleRegistry>
));

// Render sheets
// You can use the resulting sheet by inserting
// it into an HTML template.
const styles = renderSheets(styles);

CSS Processing

solid-styled uses LightningCSS to preprocess CSS templates as well as apply CSS scoping and transformations. By default, CSS Nesting and Custom Media Queries are enabled by default.

Limitations

  • Scoping css can only be called directly on components. This is so that the Babel plugin can find and transform the JSX of the component. Global css (i.e. :global or @global) can be used inside other functions i.e. hooks, utilities.
  • Dynamic styles are only limited to CSS properties.

Sponsors

Sponsors

License

MIT © lxsmnsyc

solid-styled's People

Contributors

andersk avatar bogdan0083 avatar hasali19 avatar leebeydoun avatar lxsmnsyc avatar mathieuprog avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

solid-styled's Issues

animation-bug: unwanted attributes with from/to

animations are currently not working with css, because unwanted attributes are being added to the stylesheet.

from the solidjs-template (npx degit solidjs/templates/js my-app), the animation of the logo gets compiled to:

@keyframes c-Anonymous-c8d13f94-0-logo-spin{from[s\:c-Anonymous-c8d13f94-0]{transform:rotate(0deg)}to[s\:c-Anonymous-c8d13f94-0]{transform:rotate(360deg)}}

while it should be

@keyframes c-Anonymous-c8d13f94-0-logo-spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}

solid-styled doesn't work with routing

I modified the demo example to be as minimal as possible but include routing.
If I have the css function in one of the routes, when I switch to a new route I get this error

index.mjs:1 Uncaught (in promise) DOMException: Failed to execute 'querySelector' on 'Element': 'style[s:id="example-Home-32ae95df-0-1"]' is not a valid selector.
    at Object.f [as remove] (http://127.0.0.1:5173/node_modules/.vite/deps/solid-styled.js?v=cf718557:37:27)
    at Array.<anonymous> (http://127.0.0.1:5173/node_modules/.vite/deps/solid-styled.js?v=cf718557:54:37)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1028:23)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1023:7)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1023:7)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1023:7)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1023:7)
    at cleanNode (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:1023:7)
    at updateComputation (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:733:3)
    at runTop (http://127.0.0.1:5173/node_modules/.vite/deps/chunk-MTPIYOZY.js?v=26f61b75:844:7)
f @ index.mjs:1
(anonymous) @ index.mjs:1
cleanNode @ dev.js:921
cleanNode @ dev.js:917
cleanNode @ dev.js:917
cleanNode @ dev.js:917
cleanNode @ dev.js:917
cleanNode @ dev.js:917
updateComputation @ dev.js:672
runTop @ dev.js:770
runQueue @ dev.js:840
completeUpdates @ dev.js:796
runUpdates @ dev.js:787
(anonymous) @ dev.js:499
Promise.then (async)
(anonymous) @ routing.js?v=26f61b75:268
untrack @ dev.js:421
navigateFromRoute @ routing.js?v=26f61b75:228
handleAnchorClick @ routing.js?v=26f61b75:338

Here's the minimal reproduction I made
https://github.com/orenelbaum/solid-styled-routing-bug

The same also holds for the Solid Start template, see
solidjs/solid-start#508

fresh install - help to setup

The Error:
solid-styled.js Uncaught (in promise) Error: Unexpected use of css. Make sure that solid-styled's plugin is setup correctly.

Tested with fresh installs of,

vite 4.4.5 solidjs 1.7.8
vite 5.0.0 reverted to 4.4.5 solidjs 1.8.5 (Vite 5 not yet compatible with solidjs)


npm i solid-styled
npm i -D postcss

In app.jsx added before the App function return statement:
import { css } from 'solid-styled';

css`
    .read-the-docs {
      color: red;
    }
  `;

Then error in browser console as mentioned at the top.

Also tried <style jsx>{...} in the return statement, but the result is no different than without solid-styled installed. There is still no scoping all is global. There is no errors as I imported nothing, when using the style tag, should I be importing something, as your docs are unclear here?


Is this fixable? Thanks for any help you may give.

Composition of common rules

In several instances, I repeat a set of css styles, for example for a button I will have a set of css rules which will also be used for a anchor tag as well. Ex:

const commonStyles = `
  padding: 1em;
`

const Button = () => {
  css` button { ${commonStyles} }`
  return <button></button>
}

const AButton = () => {
  css` a { ${commonStyles} }`
  return <a></a>
}

However, trying to accomplish this with solid-styled I run into the problem that the inserted string is converted to a variable.

Note that I will also have some specific styles in the css (not shown in example) so using a dynamic component doesn't make sense. (Ex: sharing border and focus styles between input and textarea, but adding additional styling in the respective components themselves)

Is there a way to compose styles (or insert style strings inside the css)?

Animation css in wrong order

Hi, both scoped and global, reorder css and prevents proper animation.

Working fine in normally imported CSS and Module imported CSS

Error only occurs with solid-styled v0.10.0

Correct Order:

      .revealingImage {
        view-timeline-name: --revealing-image;
        view-timeline-axis: block;

        animation: linear reveal both;
        animation-timeline: --revealing-image;
        animation-range: cover 10% contain 40%;
      }

Error using <styles jsx>, css``

image

Error using <styles jsx global>

image

After manually changing in browser dev tools to get it working

image

Source Code and Polyfill js taken from https://developer.chrome.com/docs/css-ui/scroll-driven-animations

New CSS properties for 2024

@global is broken

Hello,

the @global rule seems to be broken

it's wrapping the styles in an "@global {...}"

function App() {
    css`
        @global { body { background: white } }
    `
    return <main />
}

should compile to

body { background: white }

but instead it compiles to

@global { body { background: white } }

downgrading to 0.8.2 fixed the issue. maybe due to moving away from postcss?

FYI, performance of attribute selectors is (relatively) poor

I'm so excited that this library exists! Thanks for publishing it!

Just wanted to pass along some info which you may or may not already be aware of:

I notice that this package is using attribute selectors to scope the CSS. This is the same approach Angular uses to scope component css but it differs from the approach taken by the styled-jsx package.

Something you may or may not already know is that attribute selectors have poor performance relative to other selectors. Since css is interpreted right-to-left, in some cases this package's use of attribute selectors won't make much of a difference, but in other cases it will.

For example, div[data-s-xxxx] theoretically has worse performance than just div and also worse performance than div *. Meanwhile, div[data-s-xxxx].myClass has performance dictated by myClass so the use of the attribute selector shouldn't matter. I say "theoretically" because this isn't something I've benchmarked personally but I've read a few articles now that have consistently placed attribute selectors at the bottom in terms of performance.

Of course, given that Angular successfully uses attribute selectors to scope css, I'm guessing the current approach is fine. But as someone who has used Angular a lot, I also don't consider it the most performant framework so it's not obvious that it's something to emulate. Either way, I expect very few websites will be large enough for attribute selector vs class selector to matter (and I don't expect it will matter for me, personally).

Exported components from a rollup package used in Astro return error of incorrect `css` usage

Using a solid-styled component inside astro locally works fine ex:

https://github.com/xypnox/xip/blob/5a7d8731d9b9bde7d4d688870551d8ec23628226/packages/xip-warehouse/src/components/pureStyled.tsx#L1-L12

However, using from a package: https://github.com/xypnox/xip/blob/5a7d8731d9b9bde7d4d688870551d8ec23628226/packages/xip-warehouse/src/components/ui.tsx#L15-L22

Results in the error: Unexpected use of css. Make sure that solid-styled's plugin is setup correctly.

Error: Unexpected use of `css`. Make sure that solid-styled's plugin is setup correctly.
    at invariant (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected][email protected]/node_modules/solid-styled/dist/esm/development/index.mjs:165:10)
    at Module.css (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected][email protected]/node_modules/solid-styled/dist/esm/development/index.mjs:170:9)
    at Column (/home/xypnox/Projects/x/xip/packages/xip-ui/dist/source/components/elements/base.jsx:19:5)
    at Module.createComponent (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/dist/server.js:353:15)
    at Column (/home/xypnox/Projects/x/xip/packages/xip-warehouse/src/components/ui.tsx:21:3)
    at Module.createComponent (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/dist/server.js:353:15)
    at UIElements (/home/xypnox/Projects/x/xip/packages/xip-warehouse/src/components/ui.tsx:66:27)
    at Module.createComponent (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/dist/server.js:353:15)
    at renderFn (/home/xypnox/Projects/x/xip/node_modules/.pnpm/@[email protected][email protected][email protected]_@[email protected][email protected][email protected]_/node_modules/@astrojs/solid-js/dist/server.js:42:14)
    at file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/web/dist/server.js:128:34
    at createRoot (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/dist/server.js:58:14)
    at Module.renderToString (file:///home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]/node_modules/solid-js/web/dist/server.js:126:14)
    at Object.renderToStaticMarkup (/home/xypnox/Projects/x/xip/node_modules/.pnpm/@[email protected][email protected][email protected]_@[email protected][email protected][email protected]_/node_modules/@astrojs/solid-js/dist/server.js:70:8)
    at Object.check (/home/xypnox/Projects/x/xip/node_modules/.pnpm/@[email protected][email protected][email protected]_@[email protected][email protected][email protected]_/node_modules/@astrojs/solid-js/dist/server.js:15:47)
    at renderFrameworkComponent (/home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/astro/dist/runtime/server/render/component.js:98:33)
    at async Module.renderComponent (/home/xypnox/Projects/x/xip/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected][email protected]/node_modules/astro/dist/runtime/server/render/component.js:361:10)

Reference

Re-Global Dynamics - no change seen

Hi Alexis, I feel really dumb having to ask how-to, I appreciate the time your taking.

As I could not get it working on my test project, I did a fresh install of everything,
then as using your example, I simplified it, to see what's going on.
I'm not seeing any changes when dynamically adding CSS properties in the Global Scope.

In my example, if I replace the const values with hardcoded values all is good.

import { css, StyleRegistry } from "solid-styled";

function ToggleButton() {
  const globalButton = "blueviolet";
  const localButton = "yellowgreen";
  css`
    :global(button) {
      width: 50vw;
      padding: 0.5rem;
      border: none;
      color: white;
      font-size: 2rem;
      border-radius: 0.5rem;
      background-color: ${globalButton};
    }
    button {
      background-color: ${localButton};
    }
  `;
  return <button type="button">Local Button</button>;
}

function Main() {
  css`
    :global(body) {
      display: flex;
      align-items: center;
      justify-content: center;
    }
  `;

  return (
    <>
      <ToggleButton use:solid-styled />
      <br />
      <button type="button">Global Button</button>
    </>
  );
}

export default function App() {
  return (
    <StyleRegistry>
      <Main />
    </StyleRegistry>
  );
}

What have I missed here? Thanks.

P.S. I used the vite plug-in, not the unpluggin. (Thanks for the peer updates)

Doesn't work with astro

error :

Unexpected use of css. Make sure that solid-styled's plugin is setup correctly.

configuration:
I tried this

export default defineConfig({
    integrations: [solidJs(), integratePaths()],
    plugins : [
        solidStyled({
            prefix: 'my-prefix', // optional
            filter: {
                include: 'src/**/*.{ts,js,tsx,jsx}',
                exclude: 'node_modules/**/*.{ts,js,tsx,jsx}',
            },
        }),
    ]
});

also this

function integratePaths() {
    return {
        name: 'anique-solid-vite-config',
        hooks: {
            'astro:config:setup': ({updateConfig}) => {
                updateConfig({
                    vite: {
                        plugins : [
                            solidStyled({
                                prefix: 'my-prefix', // optional
                                filter: {
                                    include: 'src/**/*.{ts,js,tsx,jsx}',
                                    exclude: 'node_modules/**/*.{ts,js,tsx,jsx}',
                                },
                            }),
                        ]
                    },
                });
            },
        },
    };
}
export default defineConfig({
    integrations: [solidJs(), integratePaths()]
});

Doesn't seem to work with Solid Start's filesystem routes

So, I have a page in src/routes/index.tsx:

export default function Home() {
  css`
    #container {
      width: 100%;
      display: flex;
      flex-direction: row;
      gap: 32px;
    }
    
    #sidebar {
      max-width: 100px;
    }
    
    #main {
      flex-grow: 1;
    }
  `
  return (
    <div id="container">
      <div id="sidebar">Hello this is sidebar</div>
      <div id="main">Hello this is main</div>
    </div>
  );
}

However, these styles are not getting applied to the website:
image
image
There are no errors in the console, it just straight up refuses to work.
What's interesting, is that it seems to work inside the src/root.tsx file.

resepect postcss plugins?

Hey,

I have a Vite based project with postcss.config.cjs that have some plugins,
Since this package is postcss based, would it be possible to respect the postcss plugins as well?

Thanks.

Using css tempalte tag in solid-start routes/pages results in an error.

Using css tempalte tag in solid-start routes/pages causes an error.
Minimum repro example:

import { css } from 'solid-styled'

export default function Page() {
    css`
        .content {
            padding: 2rem;
        }
    `
    return (
        <main>
            <div class="content">This is a plain card</div>
        </main>
    )
}

Error:

Unexpected use of `css`. Make sure that solid-styled's plugin is setup correctly.

Using css template on other components (e.g. ~/components/Component.tsx) works perfectly fine.

Config:

export default defineConfig({
    vite: {
        plugins: [
            solidStyled({
                filter: {
                    include: 'src/**/*.tsx',
                    exclude: 'node_modules/**/*.{ts,js}',
                },
            }) as PluginOption,
        ],
    },
})

TypeError: (0 , import_vite_plugin_solid_styled.default) is not a function

I am getting this error when trying to setup solid-styled with vite. It's possible that I am missing something small here but I have failed to figure it out:

yarn run v1.22.19
$ vite
failed to load config from /Users/ammarahmed/Repos/apps/openotp/vite.config.ts
error when starting dev server:
TypeError: (0 , import_vite_plugin_solid_styled.default) is not a function
    at Object.<anonymous> (/Users/ammarahmed/Repos/apps/openotp/vite.config.ts:42:49)
    at Module._compile (node:internal/modules/cjs/loader:1165:14)
    at Object._require.extensions.<computed> [as .js] (file:///Users/ammarahmed/Repos/apps/openotp/node_modules/vite/dist/node/chunks/dep-4d3eff22.js:64524:24)
    at Module.load (node:internal/modules/cjs/loader:1043:32)
    at Function.Module._load (node:internal/modules/cjs/loader:878:12)
    at Module.require (node:internal/modules/cjs/loader:1067:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at loadConfigFromBundledFile (file:///Users/ammarahmed/Repos/apps/openotp/node_modules/vite/dist/node/chunks/dep-4d3eff22.js:64532:21)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async loadConfigFromFile (file:///Users/ammarahmed/Repos/apps/openotp/node_modules/vite/dist/node/chunks/dep-4d3eff22.js:64388:28)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

vite.config.ts:

import { defineConfig } from "vite";
import solidPlugin from "vite-plugin-solid";
import solidStyledPlugin from "vite-plugin-solid-styled";

export default defineConfig({
  plugins: [
    solidPlugin(),
    solidStyledPlugin({
      filter: {
        include: "src/**/*.{ts,js,tsx,jsx}",
        exclude: "node_modules/**/*.{ts,js,tsx,jsx}",
      },
    }),
  ],
  server: {
    port: 3000,
  },
  build: {
    target: "esnext",
  },
});

package.json:

{
  "name": "vite-template-solid",
  "version": "0.0.0",
  "description": "",
  "scripts": {
    "start": "vite",
    "dev": "vite",
    "build": "vite build",
    "serve": "vite preview"
  },
  "license": "MIT",
  "devDependencies": {
    "postcss": "^8.4.23",
    "typescript": "^5.0.4",
    "vite": "^4.3.8",
    "vite-plugin-solid": "^2.7.0",
    "vite-plugin-solid-styled": "^0.9.1"
  },
  "dependencies": {
    "@solidjs/router": "^0.8.2",
    "buffer": "^6.0.3",
    "solid-icons": "^1.0.4",
    "solid-js": "^1.7.5",
    "solid-styled": "^0.9.0",
    "solid-toast": "^0.5.0"
  }
}

SolidJS Version: 1.7.5

Global dynamic values scope locally only

Anything with a dynamic value is scoped locally, If I replace the signals or const with say "red" my app buttons are changed.
The same using the css import with :global(button){...};

      <style jsx global>
        {`
          button {
            color: ${color()};
            border: solid 2px rgb(128, 0, 105);
            outline: 4px dotted ${color()};
          }
          button:focus,
          button:focus-visible {
            outline: 8px ridge rgba(170, 50, 220, 0.6);
            border-radius: 2rem;
          }
        `}
      </style>

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.