Radix Colors for Flutter

Radix Colors

A gorgeous, accessible color system An open-source color system for designing beautiful, accessible websites and apps. A dart library for Radix Colors

View the Flutter web demo

Installation

Add the Radix Colors package to pubspec.yaml

dependencies:
  radix_colors: ^1.0.3

Import the package in your dart file

import 'package:radix_colors/radix_colors.dart';

Usage

Radix Colors provides 15 color scales, designed for white foreground text at step 9.

Light color variant

RadixColors.amber;

Dark color variant

RadixColors.dark.amber;

Dynamic color for auto light/dark theme

RadixColorsDynamic(context).amber;

12 Colors steps/shades

RadixColors.amber.step1;
RadixColors.amber.step2;
RadixColors.amber.step3;
RadixColors.amber.step4;
RadixColors.amber.step5;
RadixColors.amber.step6;
RadixColors.amber.step7;
RadixColors.amber.step8;
RadixColors.amber.step9;
RadixColors.amber.step10;
RadixColors.amber.step11;
RadixColors.amber.step12;

There are 12 steps in each scale. Each step was designed for at least one specific use case.

StepUse case
1App background
2Subtle background
3UI element background
4Hovered UI element background
5Active Selected UI element background
6Subtle borders and separators
7UI element border and focus rings
8Hovered UI element border
9Solid backgrounds
10Hovered solid backgrounds
11Low-contrast text
12High-contrast text

Steps 1 and 2 are designed for app backgrounds and subtle component backgrounds. You can use them interchangeably, depending on the vibe you're going for.

Appropriate applications include:

  • Main app background
  • Striped table background
  • Code block background
  • Card background
  • Sidebar background
  • Canvas area background

Steps 3, 4, and 5 are designed for UI component backgrounds.

  • Step 3 is for normal states.
  • Step 4 is for hover states.
  • Step 5 is for pressed or selected states.

Even if your component has a transparent background in its default state, you should skip Step 3 and use Step 4 for its hover state.

For call-to-action components that you want to draw particular attention to, you can bump each color one step higher to steps 4, 5, and 6.

For complex components where you need many subtle colors to communicate different meanings, you can get creative and do something like:

  • Step 3 for hovered backgrounds.
  • Step 4 for selected / pressed backgrounds.
  • Step 5 for "unread" backgrounds.
  • Step 6 for hovered "unread" backgrounds.

Steps 6, 7, and 8 are designed for borders.

  • Step 6 is designed for subtle borders on components which are not interactive. For example sidebars, headers, cards, alerts, and separators.
  • Step 7 is designed for borders on interactive components, but can also be used for focus rings.
  • Step 8 is designed for borders on interactive components in their hover state.

Steps 9 and 10 are designed for solid backgrounds.

Step 9 has the highest chroma of all steps in the scale. In other words, it's the purest step, the step mixed with the least amount of white or black. Because 9 is the purest step, it has a wide range of applications:

  • Website/App backgrounds
  • Website section backgrounds
  • Header backgrounds
  • Component backgrounds
  • Graphics/Logos
  • Overlays
  • Coloured shadows
  • Accent borders

Step 10 is designed for component hover states, where step 9 is the component's normal state background.

Most step 9 colors are designed for white foreground text. RadixColors.sky, RadixColors.mint, RadixColors.lime, RadixColors.yellow, and RadixColors.amber are designed for black foreground text and steps 9 and 10.

Steps 11 and 12 are designed for text.

  • Step 11 is designed for low-contrast text.
  • Step 12 is designed for high-contrast text.

A major part of this documentation was lifted from the Radix Colors website.

Found an issue or have a suggestion?

Create an issue

Contact

Reach me on Twitter @lesliearkorful

Use this package as a library

Depend on it

Run this command:

With Flutter:

 $ flutter pub add radix_colors

This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get):

dependencies:
  radix_colors: ^1.0.3

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:radix_colors/radix_colors.dart'; 

example/lib/main.dart

// ignore_for_file: library_private_types_in_public_api

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:radix_colors/radix_colors.dart';
import 'package:url_launcher/url_launcher_string.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Brightness brightness = Brightness.light;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Radix Colors Demo',
      theme: ThemeData(
        brightness: brightness,
        primarySwatch: Colors.blue,
      ),
      home: Builder(builder: (context) {
        return Scaffold(
          backgroundColor: RadixColorsDynamic(context).gray.step1,
          appBar: AppBar(
            elevation: 0,
            backgroundColor: RadixColorsDynamic(context).gray.step1,
            foregroundColor: RadixColorsDynamic(context).gray.step12,
            systemOverlayStyle: SystemUiOverlayStyle.dark,
            title: const Text(
              'Flutter Radix Colors',
              style: TextStyle(fontSize: 16),
            ),
            leading: IconButton(
              onPressed: () {
                setState(() {
                  if (brightness == Brightness.dark) {
                    brightness = Brightness.light;
                  } else {
                    brightness = Brightness.dark;
                  }
                });
              },
              icon: Icon(
                brightness == Brightness.dark
                    ? Icons.sunny
                    : Icons.nightlight_outlined,
              ),
            ),
            actions: [
              TextButton(
                onPressed: () {
                  launchUrlString("https://pub.dev/packages/radix_colors");
                },
                child: const Text("View on pub.dev"),
              ),
            ],
          ),
          body: SingleChildScrollView(
            padding: const EdgeInsets.symmetric(vertical: 50, horizontal: 14),
            child: Align(
              alignment: Alignment.topCenter,
              child: ConstrainedBox(
                constraints: const BoxConstraints(maxWidth: 840),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        Text(
                          "A gorgeous, accessible color system",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 28,
                            letterSpacing: -1,
                            fontWeight: FontWeight.w600,
                            color: RadixColorsDynamic(context).gray.step12,
                          ),
                        ),
                        const SizedBox(height: 12),
                        Text(
                          "An open-source color system for designing beautiful, accessible websites and apps.",
                          textAlign: TextAlign.center,
                          style: TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w300,
                            color: RadixColorsDynamic(context).gray.step11,
                          ),
                        ),
                        const SizedBox(height: 40),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            OutlinedButton(
                              onPressed: () {
                                launchUrlString(
                                  "https://pub.dev/documentation/radix_colors/latest/",
                                );
                              },
                              child: const Text("API Documentation"),
                            ),
                            const SizedBox(width: 16),
                            OutlinedButton(
                              onPressed: () {
                                launchUrlString(
                                  "https://www.radix-ui.com/colors",
                                );
                              },
                              child: const Text("Radix Documentation"),
                            ),
                          ],
                        ),
                      ],
                    ),
                    const SizedBox(height: 80),
                    colorSteps(),
                    const SizedBox(height: 6),
                    ...RadixColorsDynamic(context)
                        .primaries
                        .take(28)
                        .map((color) {
                      return colorBlock(
                          "${color.name?.substring(0, 1).toUpperCase()}${color.name?.substring(1, color.name?.length)}",
                          color);
                    }).toList(),
                    const SizedBox(height: 80),
                    Text(
                      "The Scale",
                      style: TextStyle(
                        fontSize: 22,
                        fontWeight: FontWeight.w600,
                        color: RadixColorsDynamic(context).gray.step12,
                      ),
                    ),
                    const SizedBox(height: 12),
                    Text(
                      "An overview of all 30 Radix Colors scales.\nWhite and black are excluded from this demo",
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.w300,
                        color: RadixColorsDynamic(context).gray.step10,
                      ),
                    ),
                    const SizedBox(height: 40),
                    Text(
                      "Colors",
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.w600,
                        color: RadixColorsDynamic(context).gray.step12,
                      ),
                    ),
                    const SizedBox(height: 12),
                    Text(
                      "Radix Colors provides 15 color scales, designed for white foreground text at step 9."
                      "\nThe RadixColorsDynamic class returns the matching color scale for the current Theme.brightness",
                      style: TextStyle(
                        fontSize: 14,
                        fontWeight: FontWeight.w300,
                        color: RadixColorsDynamic(context).gray.step10,
                      ),
                    ),
                    const SizedBox(height: 60),
                    ...colorMap().map((color) {
                      return Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text(
                            color.name,
                            style: const TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.w600,
                            ),
                          ),
                          const SizedBox(height: 16),
                          colorSteps(),
                          colorBlock(color.name.toLowerCase(), color.primary),
                          colorBlock(
                              "${color.name.toLowerCase()}A", color.accent),
                          colorBlock(
                            "${color.name.toLowerCase()}Dark",
                            color.primaryDark,
                          ),
                          colorBlock(
                            "${color.name.toLowerCase()}DarkA",
                            color.accentDark,
                            bg: color.primaryDark.step1,
                          ),
                          const SizedBox(height: 56),
                        ],
                      );
                    }),
                  ],
                ),
              ),
            ),
          ),
        );
      }),
    );
  }

  Widget colorBlock(String name, RadixColor color, {Color? bg}) {
    return SizedBox(
      height: 36,
      child: Row(
        children: [
          Container(
            width: 100,
            alignment: Alignment.centerLeft,
            child: Text(
              name,
              style: TextStyle(
                fontSize: 12,
                fontWeight: FontWeight.w300,
                color: RadixColors.gray.step10,
              ),
            ),
          ),
          colorBox(color.step1, bg),
          colorBox(color.step2, bg),
          colorBox(color.step3, bg),
          colorBox(color.step4, bg),
          colorBox(color.step5, bg),
          colorBox(color.step6, bg),
          colorBox(color.step7, bg),
          colorBox(color.step8, bg),
          colorBox(color.step9, bg),
          colorBox(color.step10, bg),
          colorBox(color.step11, bg),
          colorBox(color.step12, bg),
        ],
      ),
    );
  }

  Widget colorBox(Color color, Color? bg) {
    return Expanded(
      child: Container(
        color: bg,
        margin: const EdgeInsets.only(right: 2, bottom: 2),
        child: Container(
          color: color,
          width: double.infinity,
          height: double.infinity,
        ),
      ),
    );
  }

  Widget colorSteps() {
    return Row(
      children: [
        const SizedBox(width: 70),
        ...List.generate(12, (index) {
          return Expanded(
            child: Container(
              alignment: Alignment.center,
              padding: const EdgeInsets.only(bottom: 4),
              child: Text(
                "${index + 1}",
                style: const TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.w300,
                  color: RadixColors.gray,
                ),
              ),
            ),
          );
        }),
      ],
    );
  }
}

List<_ColorsDemo> colorMap() {
  return [
    _ColorsDemo(
      name: "Tomato",
      primary: RadixColors.tomato,
      accent: RadixColors.tomatoA,
      primaryDark: RadixColors.dark.tomato,
      accentDark: RadixColors.dark.tomatoA,
    ),
    _ColorsDemo(
      name: "Red",
      primary: RadixColors.red,
      accent: RadixColors.redA,
      primaryDark: RadixColors.dark.red,
      accentDark: RadixColors.dark.redA,
    ),
    _ColorsDemo(
      name: "Crimson",
      primary: RadixColors.crimson,
      accent: RadixColors.crimsonA,
      primaryDark: RadixColors.dark.crimson,
      accentDark: RadixColors.dark.crimsonA,
    ),
    _ColorsDemo(
      name: "Pink",
      primary: RadixColors.pink,
      accent: RadixColors.pinkA,
      primaryDark: RadixColors.dark.pink,
      accentDark: RadixColors.dark.pinkA,
    ),
    _ColorsDemo(
      name: "Plum",
      primary: RadixColors.plum,
      accent: RadixColors.plumA,
      primaryDark: RadixColors.dark.plum,
      accentDark: RadixColors.dark.plumA,
    ),
    _ColorsDemo(
      name: "Purple",
      primary: RadixColors.purple,
      accent: RadixColors.purpleA,
      primaryDark: RadixColors.dark.purple,
      accentDark: RadixColors.dark.purpleA,
    ),
    _ColorsDemo(
      name: "Violet",
      primary: RadixColors.violet,
      accent: RadixColors.violetA,
      primaryDark: RadixColors.dark.violet,
      accentDark: RadixColors.dark.violetA,
    ),
    _ColorsDemo(
      name: "Indigo",
      primary: RadixColors.indigo,
      accent: RadixColors.indigoA,
      primaryDark: RadixColors.dark.indigo,
      accentDark: RadixColors.dark.indigoA,
    ),
    _ColorsDemo(
      name: "Blue",
      primary: RadixColors.blue,
      accent: RadixColors.blueA,
      primaryDark: RadixColors.dark.blue,
      accentDark: RadixColors.dark.blueA,
    ),
    _ColorsDemo(
      name: "Cyan",
      primary: RadixColors.cyan,
      accent: RadixColors.cyanA,
      primaryDark: RadixColors.dark.cyan,
      accentDark: RadixColors.dark.cyanA,
    ),
    _ColorsDemo(
      name: "Teal",
      primary: RadixColors.teal,
      accent: RadixColors.tealA,
      primaryDark: RadixColors.dark.teal,
      accentDark: RadixColors.dark.tealA,
    ),
    _ColorsDemo(
      name: "Green",
      primary: RadixColors.green,
      accent: RadixColors.greenA,
      primaryDark: RadixColors.dark.green,
      accentDark: RadixColors.dark.greenA,
    ),
    _ColorsDemo(
      name: "Grass",
      primary: RadixColors.grass,
      accent: RadixColors.grassA,
      primaryDark: RadixColors.dark.grass,
      accentDark: RadixColors.dark.grassA,
    ),
    _ColorsDemo(
      name: "Orange",
      primary: RadixColors.orange,
      accent: RadixColors.orangeA,
      primaryDark: RadixColors.dark.orange,
      accentDark: RadixColors.dark.orangeA,
    ),
    _ColorsDemo(
      name: "Brown",
      primary: RadixColors.brown,
      accent: RadixColors.brownA,
      primaryDark: RadixColors.dark.brown,
      accentDark: RadixColors.dark.brownA,
    ),
    _ColorsDemo(
      name: "Sky",
      primary: RadixColors.sky,
      accent: RadixColors.skyA,
      primaryDark: RadixColors.dark.sky,
      accentDark: RadixColors.dark.skyA,
    ),
    _ColorsDemo(
      name: "Mint",
      primary: RadixColors.mint,
      accent: RadixColors.mintA,
      primaryDark: RadixColors.dark.mint,
      accentDark: RadixColors.dark.mintA,
    ),
    _ColorsDemo(
      name: "Lime",
      primary: RadixColors.lime,
      accent: RadixColors.limeA,
      primaryDark: RadixColors.dark.lime,
      accentDark: RadixColors.dark.limeA,
    ),
    _ColorsDemo(
      name: "Yellow",
      primary: RadixColors.yellow,
      accent: RadixColors.yellowA,
      primaryDark: RadixColors.dark.yellow,
      accentDark: RadixColors.dark.yellowA,
    ),
    _ColorsDemo(
      name: "Amber",
      primary: RadixColors.amber,
      accent: RadixColors.amberA,
      primaryDark: RadixColors.dark.amber,
      accentDark: RadixColors.dark.amberA,
    ),
    _ColorsDemo(
      name: "Gray",
      primary: RadixColors.gray,
      accent: RadixColors.grayA,
      primaryDark: RadixColors.dark.gray,
      accentDark: RadixColors.dark.grayA,
    ),
    _ColorsDemo(
      name: "Mauve",
      primary: RadixColors.mauve,
      accent: RadixColors.mauveA,
      primaryDark: RadixColors.dark.mauve,
      accentDark: RadixColors.dark.mauveA,
    ),
    _ColorsDemo(
      name: "Slate",
      primary: RadixColors.slate,
      accent: RadixColors.slateA,
      primaryDark: RadixColors.dark.slate,
      accentDark: RadixColors.dark.slateA,
    ),
    _ColorsDemo(
      name: "Sage",
      primary: RadixColors.sage,
      accent: RadixColors.sageA,
      primaryDark: RadixColors.dark.sage,
      accentDark: RadixColors.dark.sageA,
    ),
    _ColorsDemo(
      name: "Olive",
      primary: RadixColors.olive,
      accent: RadixColors.oliveA,
      primaryDark: RadixColors.dark.olive,
      accentDark: RadixColors.dark.oliveA,
    ),
    _ColorsDemo(
      name: "Sand",
      primary: RadixColors.sand,
      accent: RadixColors.sandA,
      primaryDark: RadixColors.dark.sand,
      accentDark: RadixColors.dark.sandA,
    ),
    _ColorsDemo(
      name: "Gold",
      primary: RadixColors.gold,
      accent: RadixColors.goldA,
      primaryDark: RadixColors.dark.gold,
      accentDark: RadixColors.dark.goldA,
    ),
    _ColorsDemo(
      name: "Bronze",
      primary: RadixColors.bronze,
      accent: RadixColors.bronzeA,
      primaryDark: RadixColors.dark.bronze,
      accentDark: RadixColors.dark.bronzeA,
    ),
  ];
}

class _ColorsDemo {
  final String name;
  final RadixColor primary;
  final RadixColor accent;
  final RadixColor primaryDark;
  final RadixColor accentDark;

  _ColorsDemo({
    required this.name,
    required this.primary,
    required this.accent,
    required this.primaryDark,
    required this.accentDark,
  });
} 

Download Details:

Author: lesliearkorful

Source Code: https://github.com/lesliearkorful/radix_colors

#radix #flutter 

Radix Colors for Flutter

UI: Beautifully Designed Components Built with Radix UI & Tailwind CSS

Shadcn/ui

Beautifully designed components built with Radix UI and Tailwind CSS.

hero

Roadmap

Warning This is work in progress. I'm building this in public. You can follow the progress on Twitter @shadcn.

  •  Toast
  •  Toggle
  •  Toggle Group
  •  Toolbar
  •  Navigation Menu
  •  Figma?

Get Started

Starting a new project? Check out the Next.js template.

npx create-next-app -e https://github.com/shadcn/next-template

Features

  • Radix UI Primitives
  • Tailwind CSS
  • Fonts with @next/font
  • Icons from Lucide
  • Dark mode with next-themes
  • Automatic import sorting with @ianvs/prettier-plugin-sort-imports

Tailwind CSS Features

  • Class merging with tailwind-merge
  • Animation with tailwindcss-animate
  • Conditional classes with clsx
  • Variants with class-variance-authority
  • Automatic class sorting with eslint-plugin-tailwindcss

Download Details:

Author: Shadcn
Source Code: https://github.com/shadcn/ui 

#react #components #ui #nextjs #tailwindcss #radix 

UI: Beautifully Designed Components Built with Radix UI & Tailwind CSS
Lawson  Wehner

Lawson Wehner

1673309940

Radix Tree implementation for Crystal

Radix Tree

Radix tree implementation for Crystal language

Installation

Add this to your application's shard.yml:

dependencies:
  radix:
    github: luislavena/radix

Usage

Building Trees

You can associate a payload with each path added to the tree:

require "radix"

tree = Radix::Tree(Symbol).new
tree.add "/products", :products
tree.add "/products/featured", :featured

result = tree.find "/products/featured"

if result.found?
  puts result.payload # => :featured
end

The types allowed for payload are defined on Tree definition:

tree = Radix::Tree(Symbol).new

# Good, since Symbol is allowed as payload
tree.add "/", :root

# Compilation error, Int32 is not allowed
tree.add "/meaning-of-life", 42

Can combine multiple types if needed:

tree = Radix::Tree(Int32 | String | Symbol).new

tree.add "/", :root
tree.add "/meaning-of-life", 42
tree.add "/hello", "world"

Lookup and placeholders

You can also extract values from placeholders (as named segments or globbing):

tree.add "/products/:id", :product

result = tree.find "/products/1234"

if result.found?
  puts result.params["id"]? # => "1234"
end

Please see Radix::Tree#add documentation for more usage examples.

Caveats

Pretty much all Radix implementations have their limitations and this project is no exception.

When designing and adding paths to a Tree, please consider that two different named parameters cannot share the same level:

tree.add "/", :root
tree.add "/:post", :post
tree.add "/:category/:post", :category_post # => Radix::Tree::SharedKeyError

This is because different named parameters at the same level will result in incorrect params when lookup is performed, and sometimes the value for post or category parameters will not be stored as expected.

To avoid this issue, usage of explicit keys that differentiate each path is recommended.

For example, following a good SEO practice will be consider /:post as absolute permalink for the post and have a list of categories which links to the permalinks of the posts under that category:

tree.add "/", :root
tree.add "/:post", :post                    # this is post permalink
tree.add "/categories", :categories         # list of categories
tree.add "/categories/:category", :category # listing of posts under each category

Implementation

This project has been inspired and adapted from julienschmidt/httprouter and spriet2000/vertx-http-router Go and Java implementations, respectively.

Changes to logic and optimizations have been made to take advantage of Crystal's features.

Contributing

  1. Fork it ( https://github.com/luislavena/radix/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Download Details:

Author: luislavena
Source Code: https://github.com/luislavena/radix 
License: MIT license

#crystal #radix #tree 

Radix Tree implementation for Crystal
Dylan  Iqbal

Dylan Iqbal

1669621194

Build a React Component Library with Radix Primitives

Learn about Radix and use Radix Primitives to develop a basic React component library as a subset of a design system. This guide aims to provide you with a deeper understanding of Radix and how it can be used to build out design systems and component libraries. 

Radix is an open source library that provides components for building accessible, high-quality React web applications and design systems. Radix is part of a new wave of headless components being created in the frontend space, and this pattern has been gaining a lot of traction lately.

This guide aims to provide you with a deeper understanding of Radix and how it can be used to build out design systems and component libraries. The latter half of this article provides an in-depth tutorial on building a sample component library with Radix Primitives. 🎨

Contents

  • Radix overview
    • Primitives
    • Colors
    • Icons
  • Design systems vs. component libraries
  • Installing and setting up the sample project
  • Building a range input component with Radix
    • Installation and boilerplate
    • Styling the range input component
    • Adding props
  • Building a tabs component with Radix
    • Installation and boilerplate
    • Adding props
    • Styling the tabs component

Radix overview

Radix is composed of a suite of three products: Primitives, Colors, and Icons. These tools can be used to build out design systems. Let’s take a closer look at each individual product and how they can be used separately or collaboratively to suit your needs.

Primitives

Radix Primitives is the library’s flagship product. It is described as a collection of “unstyled, accessible components for building high‑quality design systems and web apps in React.” Instead of reinventing the wheel, Radix Primitives handle a lot of the tricky parts when it comes to building out common component patterns.

Building out accessible widgets that meet the WAI-ARIA standards and properly handle aspects like keyboard navigation can be a large undertaking. Libraries like Radix aim to simplify this often difficult process for developers by providing a set of flexible and extensible components that are prebuilt with accessibility and developer experience in mind.

Colors

Radix Colors is a carefully crafted color system designed for building stunning web apps. It provides additional features like automatic dark mode compatibility which makes switching to a dark theme as simple as applying a class to a container, the ability to compose color palettes to work with your app’s brand or theme, and accessibility considerations that are guaranteed to pass WCAG contrast ratio requirements.

Radix Colors provides a set of scales that are JavaScript objects intended to integrate with your preferred styling solution, ranging from vanilla CSS to CSS-in-JS options (e.g., styled-components).

Icons

Radix Icons touts itself as a “crisp set of 15×15 icons designed by the WorkOS team.” All the icons are available as individual components that can be installed via a single package.

Simply import the respective icons, and you can add them to your apps like you would any other React component. Radix Icons are also available in other forms like downloadable SVGs, along with Figma and Sketch files.

Design systems vs. component libraries

I often see the terms design system and component library used interchangeably. Although these two concepts are related, they pertain to different parts of a larger whole.

In an effort to diffuse any confusion, I’ll define each term to point out the distinction and differences between the two related terminologies.

Design systems

The Nielsen Norman Group, a renowned and trusted UX research and consulting firm, defines a design system as a “…set of standards to manage design at scale by reducing redundancy while creating a shared language and visual consistency across different pages and channels.”

A typical design system may consist of the following three items:

  1. Style guide: A standard of how elements should look and feel across a suite of products or websites. The most common type of style guide relates to brand design which involves elements like fonts, typography, colors, and logos
  2. Pattern library: Typically includes templates and layout structures intended to provide general workflow patterns; the patterns established are meant to be reused and adapted throughout an application
  3. Component library: Sometimes referred to as UI libraries or UI kits

Some examples of popular design systems include Google’s Material Design, the Atlassian Design System, and Carbon Design System by IBM.

Component libraries

A component library consists of a collection of UI elements (i.e., components) that can be reused across an application. These components implement the design standards established throughout the style guide.

Due to their composability, components make it easier to implement wireframes provided by a design team. Common components found in a library range from buttons and individual form elements (e.g., inputs, checkboxes, etc.) to more complex elements like date pickers.

Some examples of popular component libraries include MUI (the artist formerly known as Material UI), Headless UI by Tailwind Labs, and of course Radix UI.

Because a design system is a large entity that often involves multiple stakeholders across varying fields, building one is quite an arduous feat. In an effort to keep this article digestible, we will build out a component library as a subset of a design system. However, it is important to note that Radix offers a full suite of tools that provide you with the resources to build out full-fledged design systems.

Installing and setting up the sample project

Documentation within a UI library is imperative because it provides a single location where developers and designers alike can view a list of the components within a design system. Developers can also leverage this documentation as a sandbox environment where they can test out components in multiple states and read up on the different properties that can be used to customize an individual component.

Because documentation is so important, our sample project has been preconfigured with React Styleguidist, a development environment for building React components. We’ll use this tool to document the components as we build them out.

To clone the radix-component-library project from GitHub, open your terminal and run the following command:

git clone https://github.com/Cool-Runningz/radix-component-library.git

Next, cd into the radix-component-library folder:

cd radix-component-library

Install the project dependencies defined in the package.json file:

npm install

Once the installation is completed, start the development server:

npm run library

Navigate to http://localhost:3020/ in your browser. You should see the following screen:

RangeInput

Now that we have the project up and running, we can begin to incorporate Radix into our component library.

Building a range input component with Radix

The first component we will build is a range input that adheres to the WAI-ARIA slider design pattern.

Creating a custom range input that has a consistent appearance across browsers can be an arduous task. However, Radix makes this process simpler by providing a Slider Primitive. The range input is sometimes referred to as a slider; throughout the rest of this article, I will use these terms interchangeably.

In Radix, each Primitive can be installed individually so you can adopt them incrementally. Primitives are also versioned independently, to further facilitate incremental adoption. This leads to less bloat in your codebases, as you only need to import the individual components that you need.

Installation and boilerplate

To build a range input component, start by installing the Slider Primitive:

npm install @radix-ui/react-slider

Next, open the RangeInput.jsx file, import the Radix Primitive, and add the boilerplate for the slider component. At this point, your file should include the following code:

import React from 'react'
import PropTypes from "prop-types"
import "./RangeInput.css"
import * as SliderPrimitive from '@radix-ui/react-slider';

const RangeInput = (props) => {
    return (
        <SliderPrimitive.Root className="rootSlider" value={props.value}>
            <SliderPrimitive.Track className="trackSlider">
                <SliderPrimitive.Range className="rangeSlider" />
            </SliderPrimitive.Track>
            <SliderPrimitive.Thumb className="thumbSlider"  />
        </SliderPrimitive.Root>
    )
}
export default RangeInput

The anatomy of a Slider component in Radix consists of the following four elements:

  1. Root: Contains all the parts of a slider
  2. Track: The track that contains the Slider.Range
  3. Range: The range part that must be contained inside Slider.Track
  4. Thumb: A draggable thumb

At this point, if you navigate to http://localhost:3020/#rangeinput you’ll notice that the UI is empty. This is because Radix components do not apply any styles by default.

Next, we’ll go through the process of adding CSS to the custom component.

Styling the component

Radix is not opinionated about how to style components and it is compatible with a variety of CSS solutions, providing you with complete control over styling.

Using plain ol’ CSS, we’ll style to RangeInput component to match the one found in the “Estimate your cost – Professional” section of LogRocket’s Pricing page:

Slider

Root

The Root contains all the parts of a slider and it will render an input for each thumb.

Create a .rootSlider class in RangeInput.css and add the following code:

 .rootSlider {
    display: flex;
    align-items: center;
    position: relative;
    height: 1.5rem;
    max-width: 30rem;
}

Track

The Track contains the Slider.Range and is the part of the slider that the thumb runs along.

Create a .trackSlider class in RangeInput.css and add the following code:

.trackSlider {
    background-color: #fafafa;
    border: 1px solid #d3d3d3;
    position: relative;
    flex-grow: 1;
    border-radius: 10px;
    height: 1rem;
}

Range

The Range must live inside Slider.Track and represents the range of values that is selected.

Create a .rangeSlider class in RangeInput.css and add the following code:

.rangeSlider {
    position: absolute;
    background: linear-gradient(90deg,#252678,#764abc);
    height: 100%;
    border-radius: 10px;
}

Thumb

The Thumb is the element on the track that the user can move around to select varying range values.

Create a .thumbSlider class in RangeInput.css and add the following code:

.thumbSlider {
    display: block;
    width: 20px;
    height: 20px;
    background-color: #764abc;
    border-radius: 30px;
    border: 1px solid #d9d9d9;
}

.thumbSlider:hover {
    cursor: pointer;
}

.thumbSlider:focus {
    outline: 1px solid white;
}

With all these styles applied, if you navigate back to http://localhost:3020/#rangeinput you should see the following being rendered:

RangeInput CSS Applied

Adding props

The last step of building the RangeInput component is to configure it to be able to accept props, which in turn will make it more reusable and customizable. For this example, we‘ll add three props:

  1. label: Applied as the aria-label value for the element with the slider role
  2. value: Represents the controlled value of the slider and must be used in conjunction with onValueChange
  3. onValueChange: The event handler that gets called when the value changes

Radix components can be controlled or uncontrolled. Adding the value and onValueChange props will turn the RangeInput into a controlled component.

The markdown file that renders the RangeInput in the sandbox environment has been preconfigured to pass in props. Now we need to update the component to be able to handle those props.

First, we need to add typechecking with PropTypes. The prop-types library has already been imported near the top of RangeInput.jsx so now you can add the propTypes definition at the bottom of the file, like so:

RangeInput.propTypes = {
    /** Applied as the aria-label value of the element with the "slider" role  */
    label: PropTypes.string.isRequired,
    /** The controlled value of the slider. */
    value: PropTypes.arrayOf(PropTypes.number).isRequired,
    /** Event handler called when the value changes. */
    onValueChange: PropTypes.func.isRequired
}

When propTypes are present, React Styleguidist will pick up the props from the object’s declarations and display them in a table. Now, anyone looking at this example will know the exact props that are needed to properly implement this component.

React Styleguidist

Next, we want to update the JSX within RangeInput.jsx to be able to pass the props to the RangeInput component. The value and onValueChange props need to get applied to the SliderPrimitive.Root element, while the label prop needs to get applied to the SliderPrimitive.Thumb element.

With those updates, the RangeInput.jsx file should now contain the following code:

import React from 'react'
import PropTypes from "prop-types"
import "./RangeInput.css"
import * as SliderPrimitive from '@radix-ui/react-slider';

const RangeInput = (props) => {
    return (
        <SliderPrimitive.Root className="rootSlider" 
           value={props.value} onValueChange={props.onValueChange}>
            <SliderPrimitive.Track className="trackSlider">
                <SliderPrimitive.Range className="rangeSlider" />
            </SliderPrimitive.Track>
            <SliderPrimitive.Thumb className="thumbSlider" aria-label={props.label} 
            />
        </SliderPrimitive.Root>
    )
}
export default RangeInput

RangeInput.propTypes = {
    /** Applied as the aria-label value of the element with the "slider" role  */
    label: PropTypes.string.isRequired,
    /** The controlled value of the slider. */
    value: PropTypes.arrayOf(PropTypes.number).isRequired,
    /** Event handler called when the value changes. */
    onValueChange: PropTypes.func.isRequired
}

Voila!

With minimal code, we were able to leverage the Radix Slider to create an accessible and functional RangeInput component that is styled to match the LogRocket theme.

Next, we’ll demonstrate how to implement one more component for our UI library.

Building a tabs component with Radix

The second component we will build is a Tabs element that leverages the Radix Tabs Primitive. This component is constructed to adhere to the WAI-ARIA Tabs design pattern.

Installation and boilerplate

First, install the Tabs Primitive:

npm install @radix-ui/react-tabs

Next, open the Tabs.jsx file, import the Radix Primitive, and add the boilerplate for the Tabs component.

Your file should include the following code:

import React from 'react'
import PropTypes from "prop-types"
import "./Tabs.css"

import * as TabsPrimitive from "@radix-ui/react-tabs";

const Tabs = (props) => {
    return (
        <TabsPrimitive.Root>
            <TabsPrimitive.List>
                <TabsPrimitive.Trigger value="tab1">Tab 1</TabsPrimitive.Trigger>
                <TabsPrimitive.Trigger value="tab2">Tab 2</TabsPrimitive.Trigger>
            </TabsPrimitive.List>
            <TabsPrimitive.Content value="tab1">
                Content for Tab # 1
            </TabsPrimitive.Content>
            <TabsPrimitive.Content value="tab2">
                Content for Tab # 2
            </TabsPrimitive.Content>
        </TabsPrimitive.Root>
    )
}

export default Tabs

The anatomy of a Radix Tabs component consists of the following four elements:

  1. Root: Contains all the Tabs component parts
  2. List: Contains the triggers that are aligned along the edge of the active content
  3. Trigger: The button that activates its associated content
  4. Content: Contains the content associated with each trigger

If you navigate to http://localhost:3020/#tabs, the default version of the component should display like this:

Tabs Without CSS

Adding props

Next, we need to configure the Tabs component to be able to accept props. For this example, we’ll add three props:

  1. tabsList: Array of tabs to be displayed
  2. value: Controlled value of the tab to activate; this should be used in conjunction with onValueChange
  3. onValueChange: Event handler called when the value changes

Currently, the Tabs component only displays a fixed number of tabs with hardcoded values. In an effort to make the component more flexible so that it can render an arbitrary number of tabs, we will update the JSX in Tabs.jsx with the following code:

import React from 'react'
import PropTypes from "prop-types"
import "./Tabs.css"
import * as TabsPrimitive from "@radix-ui/react-tabs";

const Tabs = (props) => {
    return (
        <TabsPrimitive.Root
            className="rootTabs"
            value={props.value}
            onValueChange={props.onValueChange}
        >
            <TabsPrimitive.List className="listTabs">
                {props.tabsList.map((tab) => {
                    return (
                        <TabsPrimitive.Trigger className="triggerTabs"
                            key={tab.id || `${index}-${tab.value}`}
                            value={tab.value}
                        >
                            {tab.label}
                        </TabsPrimitive.Trigger>);
                })}
            </TabsPrimitive.List>
            {props.tabsList.map((tab) => {
                return (
                    <TabsPrimitive.Content className="contentTabs"
                        key={tab.id || `${index}-${tab.value}`} 
                         value={tab.value}
                    >
                        {tab.content}
                    </TabsPrimitive.Content>
                );
            })}
        </TabsPrimitive.Root>
    )
}

export default Tabs

Tabs.propTypes = {
    tabsList: PropTypes.arrayOf(
        PropTypes.shape({
            id: PropTypes.string,
            label: PropTypes.string.isRequired,
            content: PropTypes.element.isRequired,
            value: PropTypes.string.isRequired
        })
    ),
    /** The controlled value of the tab to activate. */
    value: PropTypes.string.isRequired,
    /** Event handler called when the value changes. */
    onValueChange: PropTypes.func.isRequired
}

Tabs.md has been pre-configured to pass in an array of items to the tabsList prop. When we navigate to http://localhost:3020/#tabs, we should see the following:

Tabs with Props

Styling the component

Similar to the previous component, we’ll use vanilla CSS to style the Tabs component to match the one found in the “Estimate your cost” section of LogRocket’s Pricing page:

Pricing Page

Root

The Root contains all the elements that are contained within the tabs component.

Create a .rootTabs class in Tabs.css and add the following code:

.rootTabs {
  background-color: white;
}

List

The List contains all the Trigger elements.

Create a .listTabs class in Tabs.css and add the following code:

.listTabs {
    align-items: center;
    display: flex;
    justify-content: center;
    margin: 0 auto;
    width: 85%;
}

Trigger

The Trigger is the button that controls displaying the selected tabs content.

Create a .triggerTabs class in Tabs.css and add the following code:

.triggerTabs {
    color: #764abc;
    font-family: "Avenir";
    background: none;
    border: none;
    display: block;
    cursor: pointer;
    font-size: 20px;
    font-weight: 500;
    opacity: 0.5;
    padding: 30px;
    position: relative;
}

.triggerTabs[data-state="active"] {
    opacity: 1;
}

.triggerTabs[data-state="active"]::after {
    background-color: #764abc;
    border-radius: 12px;
    bottom: -4px;
    content: "";
    height: 6px;
    left: 0;
    position: absolute;
    width: 100%;
}

Content

The Content contains the content that is associated with each tab.

Create a .contentTabs class in Tabs.css and add the following CSS:

.contentTabs {
   border-top: 3px solid hsla(0, 0%, 44%, 0.15);
   padding: 30px 55px;
}

With all those styles applied, if you navigate back to http://localhost:3020/#tabs you should now see the following being rendered:

Tabs with CSS Applied

This completes the second example and shows how you can leverage the Radix Tabs Primitive to quickly build a functional and accessible Tabs component that is styled to match the LogRocket theme.

Conclusion

In this article, we investigated Radix and discussed how you can use its suite of products to create design systems. Building incrementally, we used Radix Primitives to develop a basic React component library as a subset of a design system.

Developing custom components can be tricky, and incorporating features like accessibility and keyboard navigation can exponentially increase complexity, further validating the benefits of leveraging tools like Radix that aim to simplify this process.

The repository for the component library developed in this article can be found on my GitHub. In addition, you can view a deployed version of the final project here.

Thank you for reading, and happy coding!

Original article source at https://blog.logrocket.com

#react #radix

Build a React Component Library with Radix Primitives
Crypto Like

Crypto Like

1606707213

What is Radix Blockchain (EXRD) | What is EXRD token

Radix is the first layer-one protocol specifically built to serve DeFi. Decentralized finance applications are currently built on protocols that are not fit for purpose, leading to congestion, hacks and developer frustration. Radix changes this by introducing a scalable, secure-by-design, composable platform with a DeFi specific build environment to make it easy to build and launch scalable DeFi.

DeFi is a booming sector. But with this craze around the latter, users have observed limits to certain protocols, such as Ethereum (ETH) and its fees which were exploding day by day. And despite days and days of tearing our hair out, the solution is not yet there … Radix then arrived in this context by coming to propose a Blockchain based on a new consensus: Cerberus. Thanks to the latter but also to all the building blocks developed around it, Radix has specialized in processing DeFi applications. Explanations.

Warning : This sponsored article is offered to you in partnership with the company Radix. Crypto investments are risky by nature, do your own research and invest only within the limits of your financial capacity. This article does not constitute an investment invitation.

Project display

Radix starts from a simple premise: DeFi is the future of finance. The second assumption is the following: today, no Blockchain succeeds in satisfying the needs of DeFi.

And Radix intends to solve this problem! To do so, the team behind Radix focused on 3 points that they considered essential:

  • Accessibility : the ability to easily enter and exit DeFi protocols but also on the Radix Blockchain itself;
  • Cash : Liquidity is what makes a project successful or not. The Radix Blockchain natively offers features allowing projects to have pools of liquidity or other mechanisms that encourage it;
  • Choice : the more players there are on the Blockchain, the greater the choice will be, thus leaving users complete freedom. Radix has therefore put in place systems to help the arrival of new players.

And finally, these three points go together to form a virtuous circle.

virtuous circle of RadixImage taken from radixdlt.com

Indeed, accessibility leads to a greater number of users, which then leads to more liquidity, which leads to a greater number of actors wanting to come, who themselves attract more users … You understand the principle!

And all this wouldn’t work without this new consensus: Cerberus! He really is the foundation of everything. Although this is a bit technical, we invite you to read the latter’s whitepaper if you are interested!

To put it simply, Cerberus is part of the so-called “braiding” consensus family. The advantage of this consensus family is that it allows the parallelism of many treatments. Behind this weird word is simply the fact of being able to perform several tasks simultaneously.

Thanks to this, the theoretical scalability of Radix is ​​infinite. In fact, it is directly linked to the number of nodes present on the network. Thus, the more successful the Radix blockchain, the more users and applications there will be, and the more nodes there will be, and therefore the more scalability will increase. A globally winning context!

On the team side, it is rather well supplied, with many people making it up, especially on the IT development aspect.

If ever the project interests you and you want to learn more about how Radix responds to DeFi issues, the project has written a whitepaper dedicated to it!

A native token: XRD

As of this writing (early October 2020), the Radix mainnet is yet to be launched. It is scheduled for 2021.

In the meantime, the project is not left with nothing! And the token native to this blockchain, the XRD, will be represented by its equivalent in ERC20: the eXRD.

When the mainnet is launched, you will then be able to exchange your eXRDs for XRDs with a ratio of 1 to 1.

Interestingly, the supply of XRD will be managed according to specific rules.

First of all, the generation of XRD will not be done by validating a block, but by the price of the block:

  • 0.05 $ = 5% of the supply issued;
  • 0.07 $ = 10% of the supply issued;
  • $ 0.39 = 90% of the supply issued;
  • 0.43 $ = 100% of the supply issued.

The goal, according to the team, behind this show is to only create tokens if they are used. So the supply is supposed to represent Radix’s adoption, not just its longevity since launch.

Finally, XRD has an important feature: its rarefaction. Indeed, during a transaction, the transaction fees will burn. Burn is a process of destroying tokens by sending them to an unusable address.

Would you like to earn token right now! ☞ CLICK HERE

Looking for more information…

☞ Website
☞ Explorer
☞ Source Code
☞ Social Channel
Message Board
☞ Coinmarketcap

Thank you for reading! I’m highly appreciate your actions! Please share if you liked it!

#blockchain #bitcoin #crypto #radix #exrd

What is Radix Blockchain (EXRD) | What is EXRD token
Autumn  Blick

Autumn Blick

1602728640

Can Blockchain Lead Towards Self-Incentivized Open Source Development?

Long before the invention of Bitcoin, the computerized world has become dependent on open source developers. Some pieces of code such as Internet browsers, operating systems, and code libraries have become so essential that it is unanimously agreed upon that they should not be controlled by a single company, who might charge exorbitant fees for their usage, withhold the software from certain users for any reason, or do other nefarious things with the code.

With the advent of cryptocurrencies and decentralized finance (DeFi), open source development has become more important than ever. However, there is a noticeable lack of professional developers in DeFi. As a result, many emerging DeFi platforms go live as largely untested garage enterprises. Oftentimes, new DeFi smart contracts can attract millions of dollars in locked value, although there has been next to no auditing.

For example, the DeFi platform YAM encountered a small but critical bug in their code, which led to massive loss of funds only a few days after the platform was launched. The platform was rushed and it’s smart contracts were never audited. While DeFi’s approach to breakneck innovation is certainly a good thing, developers lack the right tools to avoid critical mistakes and monetary incentives are a big part of this equation.

The nature of non-profit open source development has it that the initiators of DeFi projects often cannot expect their inventions to generate significant revenue. It is thus very difficult to find professional developers and auditors. While volunteer work is an absolute must-have in a world that is becoming more and more dependent on code, there is a lot of money at stake in DeFi.

Sadly, developers are seeing very little from this money. As an investor, would you entrust a DeFi platform with your money, knowing that it was hacked together in a few days by developers who have no monetary incentive for the platform to succeed?

Current Revenue Streams

For individual open source developers, there currently is little money to be made in DeFi. Most blockchain projects are either funded by various high-dollar development funds run by the big blockchain platforms, or through venture capital. While venture capitalists typically require their funded projects to be profit-oriented, blockchain development funds are often not optimal for DeFi projects.

These funds usually incentivize development on a specific blockchain as part of their ecosystem building. This leads to DeFi projects often becoming mere copy-cats of existing DApps on Ethereum, with no real innovation. Also, this incentivizes only the development of complete user-facing DApps.

What is needed is a more granular revenue stream that is oriented towards individuals. A single developer who can solve a difficult problem in an elegant way can often generate more value to a blockchain ecosystem than a full-fledged DeFi DApp, but oftentimes, coders who develop these building blocks either don’t have the connections that allow them to turn them into a complete DApp, or they simply do not have an interest in doing so.

#blockchain #defi #radix #blockchain-developer #blockchain-top-story #what-is-dlt #defi-top-story #open-source-incentivization

Can Blockchain Lead Towards Self-Incentivized Open Source Development?