Evergreen UI

repository·master·Indexed 11 days ago

https://github.com/segmentio/evergreen

A React UI framework and design system for building enterprise-grade web applications. Evergreen provides polished, composable components with smart defaults, including a robust theming layer and support for Server Side Rendering (SSR) via ui-box. Version 7.1.9.

Tokens
55.5K
Snippets
238
Records
298
Agent score
96%

What's inside Evergreen

  1. Use the SelectMenu component

    master

    The SelectMenu component is an advanced interaction pattern for selecting one or multiple items from a dropdown list. It is built on top of the Popover component and uses react-tiny-virtual-list for efficient rendering of large option lists. It can serve as a replacement for native multiple select elements.

    function SingleSelectedItemExample() {
      const [selected, setSelected] = React.useState(null)
      return (
        <SelectMenu
          title="Select name"
          options={['Apple', 'Apricot', 'Banana', 'Cherry', 'Cucumber'].map((label) => ({ label, value: label }))}
          selected={selected}
          onSelect={(item) => setSelected(item.value)}
        >
          <Button>{selected || 'Select name...'}</Button>
        </SelectMenu>
      )
    }
  2. What is a Pulsar and when to use it

    master

    A Pulsar is a UI element designed to draw attention to specific parts of the interface contextually and gently.

    Best Practices:

    • Use for optional guidance: It should be something a user can ignore without breaking their workflow.
    • Use for context: It is effective when paired with a Tooltip to provide tips or guide users to their next action.
    • Avoid overuse: Pulsars should not be a permanent or ubiquitous part of the UI. If used everywhere, they lose their ability to signal importance.
  3. What is the difference between Select and SelectField?

    master

    Evergreen provides two distinct components for selection inputs:

    1. Select: A base text input component that acts as a styled wrapper around a native HTML select element. Use this when you need a direct mapping to a native select element.
    2. SelectField: A higher-level component designed for traditional forms. It combines a Select component with a label, description, hint, and validation messages into a single cohesive unit.
  4. Understand Dialog terminology and focus management

    master

    Terminology

    Evergreen uses the term "Dialog" rather than "Modal". "Modal" is an adjective describing an element that blocks interaction with the rest of the application, whereas "Dialog" refers to the UI element itself.

    Focus Management

    • Opening: When a Dialog opens, focus is automatically moved inside the dialog. If both a cancel and confirm button are present, the cancel button receives focus first.
    • Closing: When the Dialog closes, focus is returned to the element that was focused before the dialog was opened (typically the button that triggered it).
  5. What are UI Primitives in Evergreen?

    master

    Evergreen uses 'UI Primitives' like Pane and Card as the base for building layouts and composing components. These primitives map to the Box component from ui-box.

    Key characteristics:

    • No CSS classes required: Instead of using className, you pass CSS properties (like display, padding, margin) directly as props to the component.
    • Layout construction: Use them instead of div elements to create layouts without helper classes.
    • Property overriding: Most Evergreen components are built on Pane or Box, allowing you to pass layout properties (like marginRight) directly to them to adjust spacing or positioning.
    <Pane display="flex" padding={16} background="tint2" borderRadius={3}>
      <Pane flex={1} alignItems="center" display="flex">
        <Heading size={600}>Left Aligned</Heading>
      </Pane>
      <Pane>
        <Button marginRight={16}>Button</Button>
        <Button appearance="primary">Primary Button</Button>
      </Pane>
    </Pane>
  6. How Evergreen tables work

    master

    Evergreen provides a set of building blocks for constructing tables, but it does not use standard HTML table elements like <table>, <th>, or <tr>. Instead, the table components are primarily Pane components combined with Text.

    Because they are presentational, there is no built-in sorting functionality. You are responsible for managing the data state and sorting logic yourself.

  7. Use the Menu component and its sub-components

    master

    Evergreen provides a set of components to build structured menus. The Menu component acts as a wrapper that provides focus management for its children.

    Key sub-components include:

    • Menu.Item: A single menu item button that can contain labels, icons, and secondary text.
    • Menu.Group: Used to group related menu items together, optionally with a title.
    • Menu.Divider: A visual divider to separate groups.
    • Menu.OptionsGroup: A specialized group that functions like a radio group, useful for selection tasks like sorting or filtering.

    Note: The Menu component does not manage the dropdown/popover interaction itself; you should wrap it in a Popover component to create a dropdown menu.

    <Menu>
      <Menu.Group>
        <Menu.Item>Share...</Menu.Item>
        <Menu.Item>Move...</Menu.Item>
      </Menu.Group>
      <Menu.Divider />
      <Menu.Group>
        <Menu.Item intent="danger">Delete...</Menu.Item>
      </Menu.Group>
    </Menu>
  8. How component theming works (baseStyle, appearances, and sizes)

    master

    Evergreen components follow a consistent theming pattern inspired by Chakra UI. Most components are styled using three main properties within their theme configuration:

    1. baseStyle: The default styles applied to a component. This is where you define core properties and pseudo-states like _hover, _active, or _focus using the selectors key.
    2. appearances: Custom styles mapped to the component's appearance prop. This allows you to define new visual variants (e.g., appearance="superdanger"). Note that not all components support this.
    3. sizes: Additional styles mapped to a size prop. This allows you to define different scale variants for a component. Note that not all components support this, and for those that do, you can only configure baseStyle via the size property.
    // Example of a component theme structure
    const theme = mergeTheme(defaultTheme, {
      components: {
        Button: {
          baseStyle: { /* default styles */ },
          appearances: {
            customVariant: { /* styles for appearance="customVariant" */ }
          },
          sizes: {
            large: { /* styles for size="large" */ }
          }
        },
      },
    })
  9. Server Side Rendering (SSR) and Hydration

    master

    Evergreen supports Server Side Rendering (SSR) and automatic hydration. Because Evergreen uses a bundled CSS-in-JS solution from ui-box, it provides an extractStyles() function to facilitate style extraction during SSR.

    • For Next.js integration, refer to the ssr-next example app in the repository.
    • For GatsbyJS integration, see the community guidance in the GitHub issues.
  10. Implement virtualized tables with Table.VirtualBody

    master

    For large datasets, use Table.VirtualBody as a drop-in replacement for Table.Body. This component uses react-tiny-virtual-list to handle efficient rendering.

    Key features:

    • The body can be dynamic (flexed) without needing a fixed height.
    • You do not need to supply the total number of items upfront.
    • Rows can have dynamic heights using height="auto" (note: this may reduce performance).
    • Scroll position can be controlled via scrollOffset, scrollToIndex, and scrollToAlignment (passed down to the underlying virtual list).
    <Table>
      <Table.Head>
        <Table.SearchHeaderCell />
        <Table.TextHeaderCell>Last Activity</Table.TextHeaderCell>
        <Table.TextHeaderCell>ltv</Table.TextHeaderCell>
      </Table.Head>
      <Table.VirtualBody height={240}>
        {profiles.map((profile) => (
          <Table.Row key={profile.id} isSelectable onSelect={() => alert(profile.name)}>
            <Table.TextCell>{profile.name}</Table.TextCell>
            <Table.TextCell>{profile.lastActivity}</Table.TextCell>
            <Table.TextCell isNumber>{profile.ltv}</Table.TextCell>
          </Table.Row>
        ))}
      </Table.VirtualBody>
    </Table>