An implementation of GitHub's Primer Design System using React

Overview

Primer React

A React implementation of GitHub's Primer Design System

Documentation

Our documentation site lives at primer.style/react. You'll be able to find detailed documentation on getting started, all of the components, our theme, our principles, and more.

Installation

Install @primer/react in your project with your package manager of choice:

npm install @primer/react

// or

yarn add @primer/react

Roadmap

You can track our roadmap progress in the Roadmap Project Board, see more detail in the quarterly planning Discussions, and find a list of all the current epic tracking issues here.

Contributing

We love collaborating with folks inside and outside of GitHub and welcome contributions!

👉 See the contributing docs for more info on code style, testing, coverage, and troubleshooting.

New Component Proposals

We welcome and encourage new component proposals from internal GitHub teams! Our best work comes from collaborating directly with the teams using Primer React Components in their projects. If you'd like to kick off a new component proposal, please submit an issue using the component proposal issue template and we will get in touch!

Comments
  • Add ToggleSwitch component

    Add ToggleSwitch component

    Adds a toggle switch for turning settings on and off and immediately save the change.

    Closes https://github.com/github/primer/issues/690

    Screenshots

    ToggleSwitchDemo

    Merge checklist

    • [x] Added/updated tests
    • [x] Added/updated documentation
    • [x] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    react 
    opened by mperrotti 23
  • Remove & inline `markdown-toolbar-element` dependency

    Remove & inline `markdown-toolbar-element` dependency

    In the MarkdownEditor, we are using markdown-toolbar-element to power basic formatting tools (bold, italics, etc). However, this is a custom element and not a React component, so this strategy comes with some complications.

    The way we are using the element is by rendering it with display: none and then calling .click() on the underlying elements. This is really hacky but it's necessary because the markdown-toolbar-element package doesn't expose the underlying logic at all.

    In addition to the hackiness, the dependency is problematic because it performs side effects (registering custom elements) on import, so we have to conditionally require the dependency in a useEffect callback to avoid calling browser APIs during server-side rendering. This mix of require and import confuses transpilers and occasionally breaks things in unexpected and hard-to-debug ways (for example, see this Slack thread).

    To get around this issue, I tried using require() inside a useEffect instead (pull request). This fails due to a known bug in the JavaScript engine that causes a segmentation fault.


    So to resolve both the hackiness of this approach and the issues with SSR/unit tests, I've decided to remove the dependency altogether and inline the logic instead. The downside to this is that we are duplicating the logic in that dependency when the whole point of the dependency was to help remove duplication, but there are many upsides.

    While inlining this logic, I've tried to make as few changes as possible in order to reduce risk. This means that I left some refactoring opportunities on the table for future work - I've only made the following changes:

    1. Removed all code relating to custom elements, turning the entire thing into a hook instead
    2. Removed the insertText function in favor of using our much more robust syntheticallyChangeInput strategy. This required changing the logic inside formatting functions a bit to avoid directly passing around / mutating the HTMLTextareaElement instance.
    3. Replaced the logic inside expandSelectionToLine with the getSelectedLineRange util, since this was an easy and simple win for removing duplication
    4. Renamed some functions, arguments, and types

    An even better solution would be to extract all the logic that's shared between the PVC and PRC Markdown editors into a new common behavior dependency. This could include formatting, list editing, file handling, etc... But this is not something that I have the capacity for at the moment, and I don't want to delay this fix as it's actively blocking work on downstream teams.

    Screenshots

    There are no visual changes.

    Merge checklist

    • ~~[ ] Added/updated tests~~
    • ~~[ ] Added/updated documentation~~
    • [ ] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    Stale 
    opened by iansan5653 21
  • Update types for IconButton, ActionMenu.Button, TabNav.Link and internal consumers

    Update types for IconButton, ActionMenu.Button, TabNav.Link and internal consumers

    Describe your changes here.

    The types for these buttons have seemed incorrect for some time. This should correct these types and ensure they get proper autocompletion in IDEs. I'm not 100% sure if the polymorphism on AnchorMenu.Button is correct, but it's consistent with what the types purported to be previously as far as I can tell

    fixes https://github.com/primer/react/issues/2622 fixes https://github.com/primer/react/issues/2519

    Are there are, similar instances we should fixup while here?

    I snuck in a small change more broadly, which replaces

    const component = ({sx: sxProp = {}}) => {}
    //with
    const component = ({sx: sxProp = defaultSxProp}) => {}
    

    This should avoid a new object allocation on every render of multiple components, and potentially memo/callback/effect re-evaluations related to them. I don't expect a significant perf improvement, but this should be a small one with no negative effects

    These changes lead to many incompatible typings inside primer, which I've fixed up. I think there are likely many more typing inconsistencies in primer we should work to root out, but this should at least build as expected.

    A consideration here is "Are these fixes broad enough to be considered breaking changes" as they'll likely require consumers to update code, similar to what we've had to do here

    Merge checklist

    • [x] Added/updated tests
    • [ ] Added/updated documentation
    • [ ] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    opened by mattcosta7 20
  • Add `InlineAutocomplete` component

    Add `InlineAutocomplete` component

    Writeup adapted from github/memex#10580[^hubber-only]:

    Component Description

    A new InlineAutocomplete component that provides support for inline completion suggestions (for example, emojis) in textarea and input elements.

    Screen recording of the component being used to mention a suggested user in a multiline text box:

    https://user-images.githubusercontent.com/2294248/176513250-b3b50a5f-8dcd-4591-96fe-0116b227d72b.mov

    The component is similar in some ways to the existing Autocomplete component, but this is a somewhat different pattern in that, when a suggestion is accepted, the value is inserted into the text (hence 'inline') rather than replacing the content. This pattern is closer to an IDE-style autocomplete, where the existing Primer component uses more of a 'search suggestions' pattern.

    Supported Features

    • Stateless: suggestion visibility is fully controlled by the parent component through events and props
    • Can wrap any input or textarea element as well as PRC Input and TextArea components
    • Suggestions have a default rendering, but can be fully customized (ie, to display user avatars)
    • Supports multiple trigger types so that different suggestion types can be combined (ie, to support both user mentions and emojis in the same input)
    • Predefined hooks provide reusable, mixable behavior for the most common types of suggestions: user mentions, issue references, and emojis
    • Keyboard control: select items with arrow keys, apply items with Tab or Enter
    • Mouse control: click to select items (maintains focus on the input)
    • Undo history is preserved when applying suggestions
    • Caret position is preserved when applying suggestions

    Additional Work

    While adding this component, I also added some new hooks to abstract out some of the underlying logic:

    useCombobox hook

    The useCombobox hook provides a React-compatible wrapper around the @github/combobox-nav class. This provides keyboard control and accessible roles for comboboxes (lists of items that can be selected to apply to an input). The hook provides support for comboboxes that can be opened and closed like this one, and calls an easy to use event callback when an option is selected.

    useSyntheticChange hook

    When a suggestion is applied, we need to emit a change event from the underlying input. It should look to the API consumer as though the input was typed in - they shouldn't have to add any additional event handlers to react to suggestion application. In addition, we want to preserve the undo stack and caret position - if we have a separate event handler and just update the input's value, the caret position will be reset.

    So this hook provides an easy way to simulate a change that is as close as possible to the real thing. The change event preserves the undo stack and caret position and calls the onChange handler that is already bound to the underlying input.

    Background / Context

    In projects (beta), we are using this component to provide emoji suggestions across the entire application and also to provide support for multiple types of inline suggestions in the Markdown editor.

    This component is a dependency of the MarkdownEditor[^hubber-only] (AKA CommentBox[^hubber-only]) component as it provides the inline suggestions for # references, @ mentions, and emojis (:). Rather than open one giant PR, I wanted to split this work out into a separate task.

    🚧 IMO, this component should be added as experimental status, just like the Markdown editor itself.

    Closes github/memex#10580[^hubber-only]. There is not (at this time) a Primer tracking issue for this component.

    Risks

    New Dependencies

    Two new external dependencies are introduced:

    • @github/combobox-nav: See the useCombobox hook note above.
      • [ ] Note: Due to the way this library uses the navigator global, it's incompatible with SSR so it doesn't work with the docs. I have an open PR to fix this.
    • @koddsson/textarea-caret: Detects the position of a character index in a textarea or input element. This is used to position the suggestions list and is already used in GitHub for the existing Markdown editor.

    Accessibility

    This component dynamically adds and removes a combobox as the user is typing. A combobox that is always visible is accessible, but one that is added and removed is not - the suggestions will likely never be read by a screen reader. This issue is already present in GitHub with the existing Markdown editor. When we have the resources to solve this, we should do so by fixing the @github/combobox-nav library so the fix will cascade down to the existing Markdown editor in addition to this component.

    Storybook error

    The story works in Storybook, but there is a console error being thrown that I have not been able to fix. I'm not familiar with Slots and could use some help here if anyone has any thoughts. I can't figure out where data-source might be getting applied. Is this a Storybook-specific issue?

    Warning: Invalid prop data-source supplied to React.Fragment. React.Fragment can only have key and children props.

    at Slots
    at UserSuggestion
    at SuggestionListItem
    at ul
    at StyledComponent
    at List__ListBox
    ...
    

    Merge checklist

    • [x] Added/updated tests (working on this - it's tested as part of MarkdownEditor in projects beta; I need to extract those tests and make them specific to this component)
    • [x] Added/updated documentation
    • [x] Tested in Chrome
    • [x] Tested in Firefox
    • [x] Tested in Safari
    • [x] Tested in Edge

    Need to merge and update combobox-nav library to fix docs issue:

    • [x] https://github.com/github/combobox-nav/pull/53

    [^hubber-only]: :octocat: Link only accessible to GitHub employees

    💓collab react a11y-eng-secondary 
    opened by iansan5653 20
  • Change decision for ADR-008-experimental-components

    Change decision for ADR-008-experimental-components

    After having multiple conversations around this topic to validate our assumptions (see footnotes^1^3), I think we should change our decision to the runner up in the initial ADR


    tl;dr of diff: Instead of publishing components from github/github/modules/react-shared, we should create a new repository to keep experimental components that are shared between monolith and non-monolith projects (like memex, docs, even primer)

    why: We already have a federated model in place without putting a label on it. Each application has experimental components built for their purpose (github/github has react-shared, memex has a catalog of reusable components). When there is an opportunity to share a pattern between the monolith and memex, we need a place that's equally convenient for both teams to upstream and maintain long term.


    Initial assumptions:

    1. github/github/modules/react-shared is the easiest place for monolith developers to contribute to and we should treat memex as the exception, not the rule.
      • While the first part of the statement is true, I don't think we should treat memex as the exception. If it's difficult for developers in memex to upstream components here or maintain them over time, we wouldn't benefit from sharing them at all
      • Writing components to be published as a package is a different challenge, we would require checks to ensure a component does not import dotcom code or other internal dependencies into the published package. Assumptions made inside the monolith might not work for other projects
      • Monolith deployments have a different workflow than traditional open source libraries (example: primer/react) which will slow teams down
    2. We would publish all components from react-shared
      • Not all components in react-shared are useful to share between projects, only components that are used across pages like repos/issues and memex are useful to share.
      • Components that deal with monolith specific navigation and data fetching logic aren't helpful for non-monolith projects, the added constraints from point 1 would be unnecessary to add to all components
    3. Bonus: We did not see ourselves putting experimental or draft components from primer/react in monolith/react-shared, but a github/react-experimental repository outside the monolith would be a good place to host experimental components that are primer/react candidates (instead of keeping them in primer/react), that would add another team as shared maintainer of this new repository.

    Sidenote: We could use better visibility into potentially reusable components that have been built inside a application (thinking deployed storybook and docs)

    react skip changeset 
    opened by siddharthkp 19
  • [Suggestion][QoL] Add a rhythm property to FlexProps

    [Suggestion][QoL] Add a rhythm property to FlexProps

    rhythm is an idea I've used in the past to describe containers that kept identical spacing between their children. As an example, the phrase "with an 8-pixel vertical rhythm" means that items in the vertical list were separated vertically by 8 pixels.

    I've usually implemented this idea with a set of rhythm-$direction-$spacing CSS classes that would be applied to Flex containers like this:

    <div className="flex-column rhythm-vertical-8>{...children}</div>
    

    These classes do the following (SCSS):

    & > :not(:firstChild) {
        margin-top: $spacing; // margin-left for horizontal
    }
    

    Given that Primer's Flex component has flexDirection as a prop, exposing a rhythm prop would allow Flex to automatically generate the appropriate classes.

    This paradigm allows for a few things:

    1. Use of components that don't actually have any margin props exposed without having to manage the margins of elements around them (eg. putting an SVG between two Text elements is currently a tiny bit painful if you want any spacing)
    2. Less duplication of mr={2} on child components for these kinds of scenarios

    I'm not sure if this is a thing that's in keeping with the Primer design system, or necessarily something that Primer wants to support as a first-class idea, but I've found a notion of this handy in the past and wanted to float it as an idea.

    If this is something Primer wants to support, I'm happy to spend an hour or two this weekend opening a pull-request for it.

    fr-skip Stale 
    opened by clayplumridge 19
  • Make resizable SplitPageLayout.Pane keyboard accessible.

    Make resizable SplitPageLayout.Pane keyboard accessible.

    Added a tabIndex prop and onKeyDown event handler to PageLayout.Pane (which SplitPageLayout.Pane uses) to allow keyboard controls to change the pane's size. Only handles ArrowRight and ArrowLeft keys.

    Also added a text input that is only visible to screen readers that allows users to change the width of the pane from the minimum percentage to the maximum percentage it can take up within its parent. This is still visible to a screen reader even on narrow views where the pane width is not resizable.

    Closes #2522

    Screenshots

    Please provide before/after screenshots for any visual changes

    Merge checklist

    • [x] Added/updated tests
    • [x] Added/updated documentation
    • [x] Tested in Chrome
    • [x] Tested in Firefox
    • [x] Tested in Safari
    • [x] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    bug 
    opened by radglob 16
  • New Button component

    New Button component

    Describe your changes here.

    Building up the new button as per recommendations from https://github.com/github/primer/issues/382 and https://github.com/github/primer/issues/253

    Things done

    • Single button component
    • No outline button
    • Add icon only button
    • Add LeadingIcon
    • Add Counter
    • Add Caret button
    • Story for block button

    Todos

    • [x] Linter issues
    • [x] Type issues with forwarding
    • [x] Make all Button sizes correct
    • [x] Dialog component uses the Button wierdly for close button. Try and fix this
    • [x] Figure out all the spacings between slots from the audit
    • [ ] How will we make button changes in watch/upvote more a11y friendly
    • [ ] Attaching descriptions to buttons must be form group functionality
    • [x] Edge cases of button variants + icons + caret with different button sizes
    • [ ] Button as Link

    Screenshots

    TBD

    Merge checklist

    • [ ] Added/updated tests
    • [ ] Added/updated documentation
    • [x] Tested in Chrome
    • [x] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    react skip changeset 
    opened by pksjce 16
  • Add `sx` prop for theme-aware ad-hoc styles

    Add `sx` prop for theme-aware ad-hoc styles

    The sx prop is used by some UI libraries to allow users to apply inline, ad-hoc styles to a component while still making the styles theme-aware. I experimented a bit this afternoon and was able to come up with a proof-of-concept:

    sx prop PoC screenshot

    You can see the basic implementation in this PR, which is based around @styled-system/css, but it is essentially the following:

    const withSx = Component => {
      return function SxWrapper({sx, children, ...props}) {
        const ctxTheme = useTheme()
        if (!sx) {
          return <Component {...props}>{children}</Component>
        }
    
        const extraProps = {}
        const compiled = css(sx)(props.theme || ctxTheme)
        if (props.style) {
          extraProps.style = Object.assign({}, props.style, compiled)
        } else {
          extraProps.style = compiled
        }
    
        return (
          <Component {...props} {...extraProps}>
            {children}
          </Component>
        )
      }
    }
    
    const Heading = WithSx(styled.h1`
    // ... normal styled-component stuff here
    

    While exploring this PoC and the implementations from other libraries, I've identified the following constraints and challenges:

    Compatibility with plain DOM nodes

    This implementation only works for components explicitly wrapped with the HoC, so it wouldn't be possible to do something like <span sx={{color: 'red.5'}}>...</span>. To enable that, we'd have to create a JSX pragma, similar to Theme UI, which would need to be used in all our components and any JS file a consumer writes that wants to use the sx prop on a plain DOM node. This pragma function would then generate the correct element tree to power the prop. This would of course need some JSX intrinsics types for TypeScript.

    Another option is to introduce a hook that can produce style-prop-compatible objects with themeable values, à la useStyles({ color: 'red.5' }).

    However, neither option addresses the following concern:

    Nested styles

    styled-systems's css utility, which powers this implementation, allows for more than just plain CSS properties in the sx prop object. For example, this is a valid value for the prop:

    {
      fontSize: [ 4, 5, 6 ],
      color: 'primary',
      bg: 'gray',
      '&:hover': {
        color: 'secondary',
      },
    }
    

    However, since this generates style objects with media queries and selectors, it can't be passed directly to any DOM node.

    One solution is to use styled-component's css prop; however, the use of this prop necessitates the use of the Babel plugin (or macro) to work, and as a result, I don't think we'd be able to implement the sx prop in Primer Components (because the Babel plugin won't run). Instead, a user could use the option that @styled-system/css demonstrates:

    import React from 'react'
    import css from '@styled-system/css'
    
    // ...
    
    <div
      css={css({
      fontSize: [ 4, 5, 6 ],
      color: 'primary',
      bg: 'gray',
      '&:hover': {
        color: 'secondary',
      },
    })}
    />
    

    Since the user would have to set up the Babel plugin anyway in this case, they could simply write the above code themselves, instead of us providing a special sx prop.

    Part of me wonders if one could generate a styled-components-wrapped component on the fly using the sx prop, but my guess is no, because if so then why does styled-components require a Babel plugin for the css prop?

    status: wip 
    opened by BinaryMuse 16
  • Add resizable support to the `<PageLayout>` component

    Add resizable support to the `` component

    Describe your changes here.

    This PR adds resizable support to the <PageLayout> component.

    Screenshots

    Please provide before/after screenshots for any visual changes

    Merge checklist

    • [ ] Added/updated tests
    • [ ] Added/updated documentation
    • [ ] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    opened by japf 15
  • Simple select button for colorschemes and themeswitcher component

    Simple select button for colorschemes and themeswitcher component

    This is a documentation only change for primer/react documentation website. Added a ThemeSwitcher to the doctocat custom components. Select dropdown and logic to switch between colorSchemes. Decide which colorMode based on colorSchemes.

    Questions

    1. I'd like to use the Dropdown component, still trying to figure out which component triggers the onChange event.
    2. The relation between colorMode and colorSchemes is not well defined. The type is just a string. Is this going to be fixed in the future?

    Closes #1433

    Screenshots

    https://user-images.githubusercontent.com/417268/134846970-adc04d04-96b0-4a89-a57c-24864c961934.mp4

    Merge checklist

    • [ ] Added/updated tests
    • [x] Added/updated documentation
    • [x] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge
    opened by pksjce 15
  • Recursive tree to render theme object

    Recursive tree to render theme object

    Working on passion week project. The goal is to build a tree that renders our theme object. See https://github.com/github/design/discussions/140#discussioncomment-4471744 for more details.

    It's currently broken! Help needed.

    Screenshots

    n/a

    Merge checklist

    • [ ] Added/updated tests
    • [ ] Added/updated documentation
    • [ ] Tested in Chrome
    • [ ] Tested in Firefox
    • [ ] Tested in Safari
    • [ ] Tested in Edge
    opened by tbenning 2
  • shouldForwardProp support

    shouldForwardProp support

    Description

    Some props that are handled by the styled-system are passed down to HTML tags. Filtering out these useless attributes can reduce the size of the generated HTML.

    References

    • https://styled-system.com/guides/removing-props-from-html/
    • https://github.com/styled-components/styled-components/pull/3006
    react 
    opened by renbaoshuo 0
  • Create deprecating-components.md

    Create deprecating-components.md

    Closes https://github.com/github/primer/issues/1593

    This PR is based on deprecating React components ADR , my notes from chatting with PRC folks about the process as well as my first time deprecating a component experience. So this is a pretty much raw document that I would love to get your thoughts on 🙏🏼

    Note: I copy-pasted quite a few info from the ADR, thanks to @siddharthkp :)

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    skip changeset 
    opened by broccolinisoup 3
  • Prevent automatic batching updates in ThemeProvider to ensure client use right colorMode

    Prevent automatic batching updates in ThemeProvider to ensure client use right colorMode

    Closes #2731.

    Use ReactDOM.flushSync to prevent automatic batching of state updates since React 18, which causes error described in #2731.

    Screenshots

    None.

    Merge checklist

    • [x] ~~Added/updated tests~~
    • [x] ~~Added/updated documentation~~
    • [x] Tested in Chrome
    • [x] Tested in Firefox
    • [x] Tested in Safari
    • [x] Tested in Edge

    Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

    opened by renbaoshuo 1
  • Theming issue when using SSR

    Theming issue when using SSR

    Description

    When the colorMode property of <ThemeProvider /> is set to auto and SSR is used, it will still be displayed in light mode on browsers that prefer dark mode.

    Steps to reproduce

    1. Set the colorMode property of <ThemeProvider /> to auto.
    2. Perform Next.js SSR / SSG rendering.
    3. Open the page on the browser that prefers dark mode.
    4. The displayed color scheme is day, not night.

    Temporary patch

    Add a hook named useAutoColorMode.

    import { useEffect, useState } from 'react';
    
    import useMediaQuery from '@/hooks/useMediaQuery';
    
    enum ComponentColorMode {
      auto = 'auto',
      day = 'day',
      night = 'night',
    }
    
    const useAutoColorMode = () => {
      const [colorMode, setColorMode] = useState(ComponentColorMode.day);
      const darkModeEnabled = useMediaQuery('(prefers-color-scheme: dark)');
    
      useEffect(() => {
        setColorMode(
          darkModeEnabled ? ComponentColorMode.night : ComponentColorMode.day
        );
      }, [darkModeEnabled]);
    
      return colorMode;
    };
    
    export default useAutoColorMode;
    

    Manually set colorMode in App.tsx.

    const App = () => {
    +  const colorMode = useAutoColorMode();
    
      // ...
    
      return (
    -    <ThemeProvider colorMode="auto" preventSSRMismatch>
    +    <ThemeProvider colorMode={colorMode} preventSSRMismatch>
    

    Version

    v35.16.0

    Browser

    Chrome

    bug react 
    opened by renbaoshuo 2
Releases(v35.16.0)
  • v35.16.0(Dec 16, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.15.1(Dec 5, 2022)

  • v35.15.0(Nov 30, 2022)

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.14.2(Nov 10, 2022)

    Permalink to documentation

    Patch Changes

    • #2553 3a4b3124 Thanks @broccolinisoup! - UnderlineNav2: Only allow Enter and Space key to select an UnderlineNav item

    • #2506 a20faba0 Thanks @broccolinisoup! - UnderlineNav2: Prevent item width calculation when they are null

    • #2549 205e1d29 Thanks @mperrotti! - Adds a focus style to ActionList.LinkItem that is used when the primary input method is a cursor. Before this change, there was only a focus style for when the keyboard is being used as the primary input method.

    • #2546 8a8b1a4f Thanks @joshblack! - Add support for PageUp and PageDown for TreeView

    • #2485 e2a2d78c Thanks @broccolinisoup! - UnderlineNav2: Only run overflow layout function when nav item has a width

    • #2552 7877f895 Thanks @broccolinisoup! - UnderlineNav2: Add aria-hidden and sr-only class support for a descriptive "More" button label

    • #2550 e13e8ad7 Thanks @broccolinisoup! - UnderlineNav2: Remove focus zone and unnecessary 'Arrow keys' & 'Home' & 'End' button navigation support

    • #2551 5bc5c703 Thanks @broccolinisoup! - UnderlineNav2: Add aria-hidden and sr-only class support for descriptive counters

    • #2538 bdbccaaf Thanks @colebemis! - TreeView: Preserve expanded state of nested items when parent item is collapsed.

      Breaking change

      TreeView.Item and TreeView.LinkItem now require an id prop:

      - <TreeView.Item>...</TreeView.Item>
      + <TreeView.Item id="unqiue-id">...</TreeView.Item>
      

      This is not in a major release because TreeView is still a draft component.

    • #2555 dc1cf6da Thanks @josepmartins! - Remove deprecated components usage in Overlay stories

    Source code(tar.gz)
    Source code(zip)
  • v35.14.1(Nov 7, 2022)

    Permalink to documentation

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.14.0(Nov 1, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.13.0(Oct 25, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.12.0(Oct 19, 2022)

    Permalink to documentation

    Minor Changes

    • #2435 e335cc4b Thanks @colebemis! - SplitPageLayout has moved from @primer/react/drafts to @primer/react:

      - import {SplitPageLayout} from '@primer/react/drafts'
      + import {SplitPageLayout} from '@primer/react'
      

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.11.0(Oct 12, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.10.0(Sep 22, 2022)

    Permalink to documentation

    Minor Changes

    • #2347 09a5d806 Thanks @mperrotti! - Adds a size prop to the SegmentedControl component. Users can choose between 'medium' (default), and 'small'. More sizes can be added when/if we find we need them.

    • #2324 027e44a7 Thanks @joshblack! - Update PageLayout.Pane to support a ref on the element wrapping children

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.9.0(Sep 9, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    • #2266 4cc6e52a Thanks @siddharthkp! - ActionMenu: Fix keyboard navigation for ActionMenu inside Overlay by re-enabling focus trap. It was disabled in v35.6.0, that led to a regression for ActionMenu within focus zones (example: AnchoredOverlay)

    • #2252 e52415e1 Thanks @joshblack! - Update ButtonBase.tsx to memoize calls to styles to improve performance

    • #2318 10305092 Thanks @iansan5653! - - Fix InlineAutocomplete accessibility hint affecting page layout outside of the suggestions

      • Fix suggestion icons not being visible in InlineAutocomplete items
    • #2206 3a38e6e3 Thanks @maximedegreve! - Add missing border on avatars

    • #2294 4536b87a Thanks @joshblack! - Change the default markup of PageLayout.Pane from <aside> to <div>

    Source code(tar.gz)
    Source code(zip)
  • v35.8.0(Aug 26, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.7.0(Aug 18, 2022)

    Permalink to documentation

    Minor Changes

    • #2232 a0fcce61 Thanks @broccolinisoup! - Add a stickyTop prop, the height of a sticky header, to the PageLayout.Pane to push the pane down for the sticky header when necessary.

    • #2228 bf99db99 Thanks @mperrotti! - Moves SegmentedControl to the main bundle and updates it's lifecycle status to "Alpha"

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.6.0(Aug 16, 2022)

    Permalink to documentation

    Minor Changes

    • #2191 7edf1347 Thanks @mperrotti! - Adds responsive behavior to SegmentedControl's fullWidth prop.

    • #2174 62dbc981 Thanks @colebemis! - Add a responsive hidden prop to PageLayout.Header, PageLayout.Pane, PageLayout.Content, and PageLayout.Footer that allows you to hide layout regions based on the viewport width. Example usage:

      // Hide pane on narrow viewports
      <PageLayout.Pane hidden={{narrow: true}}>...</PageLayout.Pane>
      
    • #2199 fb385b63 Thanks @colebemis! - * Updated the position prop in PageLayout.Pane to use the new responsive prop API introduced in https://github.com/primer/react/pull/2174.

      • Deprecated the positionWhenNarrow prop in favor of the new responsive prop API

      Before

      position="start"
      positionWhenNarrow="end"
      

      After

      position={{regular: 'start', narrow: 'end'}}
      
    • #2201 885064ed Thanks @colebemis! - Add padding prop to PageLayout.Header, PageLayout.Content, PageLayout.Pane, and PageLayout.Footer

    • #2164 2b5c86e5 Thanks @mperrotti! - Adds support for a responsive 'variant' prop to the SegmentedControl component

    • #2212 04d9d9c1 Thanks @colebemis! - Add a sticky prop to the PageLayout.Pane component that provides a convenient way for you to make side panes sticky:

      <PageLayout>
      - <PageLayout.Pane>...</PageLayout.Pane>
      + <PageLayout.Pane sticky>...</PageLayout.Pane>
        <PageLayout.Content>...</PageLayout.Content>
      </PageLayout>
      
    • #2198 4d9b7db9 Thanks @colebemis! - * Updated the divider prop in PageLayout.Header, PageLayout.Pane, and PageLayout.Footer to use the new responsive prop API introduced in https://github.com/primer/react/pull/2174.

      • Deprecated the dividerWhenNarrow prop in favor of the new responsive prop API

      Before

      divider="line"
      dividerWhenNarrow="filled"
      

      After

      divider={{regular: 'line', narrow: 'filled'}}
      

    Patch Changes

    • #2024 5321f1c9 Thanks @siddharthkp! - ActionMenu: Remove focus trap to enable Tab and Shift+Tab behavior and fix initial focus on click

    • #2186 e28aadbd Thanks @mperrotti! - Updates SegmentedControl styles to use component primitives.

    • #2171 384ae6b9 Thanks @anleac! - Support issues closed as not planned, and correct the standard issue closed backgroud colour

    • #2157 77e7ab05 Thanks @iansan5653! - Add InlineAutocomplete component, useCombobox hook, and useSyntheticChange hook to drafts

    • #2189 35716587 Thanks @mperrotti! - Makes SegmentedControl uncontrolled by default.

    • #2196 5ff5bb81 Thanks @mattcosta7! - update types to allow children for react 18

    • #2219 af534f15 Thanks @iansan5653! - Fix slots infinite rendering when no context prop is provided

    • #2182 47725a92 Thanks @iansan5653! - - Add MarkdownEditor and MarkdownViewer draft components. The MarkdownEditor is also known as the CommentBox component

      • Add useUnifiedFileSelect, useIgnoreKeyboardInputWhileComposing, useDynamicTextareaHeight, and useSafeAsyncCallback draft hooks
    • #2173 ed609719 Thanks @mperrotti! - Updates styles for the Select component so that the focus outline is even all the way around.

    • #2216 82fd8c35 Thanks @iansan5653! - Change createSlots to use layout effects when registering slots

    • #2185 3756a1ed Thanks @mattcosta7! - Set ConfirmationDialog initial focus based on the confirmationButtonVariant. When danger autoFocus the cancel button, otherwise autoFocus the confirmation button

    • #2166 75d21745 Thanks @mattcosta7! - button should be polymorphic

    • #2220 f4ef7b4b Thanks @mperrotti! - - Fixes role and keyboard behavior for SegmentedControl.

      • Fixes a bug where icon-only SegmentedControl buttons did not fill the parent width when the fullWidth prop was set
      • Fixes a bug where click handlers were not passed correctly when the responsive variant was set to 'hideLabels'
    • #2204 522f5806 Thanks @iansan5653! - Replace useCombinedRefs with useRefObjectAsForwardedRef

    • #2221 9ce64937 Thanks @josepmartins! - Overlay documentation fixes

    Source code(tar.gz)
    Source code(zip)
  • v35.5.0(Jul 21, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    • #2150 63a2de51 Thanks @dgreif! - Ensure all files in lib-esm are in fact esm and not CommonJS

    • #2145 a2950ac4 Thanks @mperrotti! - Updates SegmentedControl component's keyboard navigation to align with the recommendations of GitHub's accessibility team.

    • #2143 d9b161a0 Thanks @mperrotti! - Fixes bugs in form components discovered while fixing/improving Storybook and docs.

    Source code(tar.gz)
    Source code(zip)
  • v35.4.0(Jun 30, 2022)

    Permalink to documentation

    Minor Changes

    Patch Changes

    • #2099 40da598e Thanks @siddharthkp! - AnchoredOverlay: aria-expanded attribute is removed from anchor when overlay is not open

    • #2155 003cbcf0 Thanks @mperrotti! - Update Checkbox component to useIsomorphicLayoutEffect instead of useLayoutEffect to support SSR

    • #2154 96ad635b Thanks @mperrotti! - Allow "falsely/empty" Autocomplete.Input values

    • #2153 ce45de30 Thanks @willglas! - Add AutocompleteContext to Autocomplete component exports

    • #2105 c7bbd06f Thanks @siddharthkp! - ActionMenu: Replace typeahead behavior with single key mnemonics

    • #2125 78dc8134 Thanks @owenniblock! - Adds roles of tablist and tab to the TabNav component, required rearranging the HTML elements to be semantically correct

    • #2149 b3a98bac Thanks @dgreif! - Converted commonjs require of focus-visible to an esm import

    • #2120 53713b2f Thanks @colebemis! - Deprecate SideNav in favor of NavList.

      Before

      <SideNav aria-label="Main">
        <SideNav.Link href="/" selected>
          Home
        </SideNav.Link>
        <SideNav.Link href="/about">About</SideNav.Link>
        <SideNav.Link href="/contact">Contact</SideNav.Link>
      </SideNav>
      

      After

      <NavList aria-label="Main">
        <NavList.Item href="/" aria-current="page">
          Home
        </NavList.Item>
        <NavList.Item href="/about">About</NavList.Item>
        <NavList.Item href="/contact">Contact</NavList.Item>
      </NavList>
      
    • #2133 65fcd9f2 Thanks @mattcosta7! - Passthrough ActionList.Group props from NavList.Group

    • #2158 ac92de47 Thanks @owenniblock! - Fixes issue when tabs are not links

    Documentation

    https://primer.style/react

    https://primer-1ccf29cffb-13348165.drafts.github.io

    Source code(tar.gz)
    Source code(zip)
  • v35.3.0(Jun 20, 2022)

    Minor Changes

    Patch Changes

    • #2083 ea69ccd6 Thanks @ty-v1! - Export new Dialog component from the @primer/react/drafts bundle:

      - import {Dialog} from '@primer/react/lib-esm/Dialog/Dialog'
      + import {Dialog} from '@primer/react/drafts'
      
    • #2117 6e3532cf Thanks @dgreif! - Allow minor version updates for production dependencies

    • #2095 db5e629c Thanks @hectahertz! - Communicate the SelectPanel multi-select capability to assistive technologies.

    Documentation

    https://primer-3d95468836-13348165.drafts.github.io/

    Source code(tar.gz)
    Source code(zip)
  • v35.2.2(May 24, 2022)

    Patch Changes

    • #2058 ab30f14a Thanks @colebemis! - Add draft of NavList component

    • #2038 1c2eeb9c Thanks @mperrotti! - Fixes accessibility bugs in the Select component.

    • #2076 05301033 Thanks @colebemis! - Draft NavList.Item now accepts an as prop, allowing it to be rendered as a Next.js or React Router link

    • #2082 3252b74c Thanks @mperrotti! - Fixes broken links in the documentation

    • #2075 56dbbd32 Thanks @colebemis! - Fix overflow issues in PageLayout.Content

      | Before | After | | ----------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | | image | image |

    • #2087 b319b29d Thanks @mperrotti! - Prevents the onRemove prop from being passed through to the HTML element from Token, AvatarToken, and IssueToken.

    • #2077 30f93ffb Thanks @colebemis! - Adds support for the sx prop on the draft implementation of NavList and all its subcomponents (e.g., NavList.Item)

    • #2050 0f9edcac Thanks @mperrotti! - Finishes updating components with the global focus styles defined in Primer CSS (this PR)

    • #2054 a682735f Thanks @colebemis! - Fixes layout bug with ButtonGroup by changing the display property from inline-block to inline-flex

    • #2064 62d90af8 Thanks @colebemis! - Add support for sub-items in draft implementation of NavList

    • #2057 c8f7e235 Thanks @mperrotti! - - adds color-scheme style to inputs so they get the correct user-agent dark/light styles

      • crops ToggleSwitch knob's shadow inside the toggle switch boundaries
      • changes FormControl styles to prevent <select>, <textarea>, <input> from filling the parent's width when the block prop has not been passed to the input component
    • #2048 4e15985b Thanks @siddharthkp! - ThemeProvider: Bug fix, in colorMode=auto, the theme now syncs with system changes.

    Source code(tar.gz)
    Source code(zip)
  • v35.2.1(May 3, 2022)

    Patch Changes

    • #2013 5f6c5e22 Thanks @mperrotti! - 1. Fix a spacing issue with the loading spinner in a TextInputWithTokens

      1. Bolds form validation text to be visually balanced with the icon
    • #2053 231c70b9 Thanks @langermank! - Namespace UnderlineNav

    • #2033 0d7a871a Thanks @mperrotti! - - Text input inner action's hover bg should not touch the text input edges

      • Increases touch target area of the text input inner action button
      • Deprecated children and variant props on the TextInputInnerAction component, but they're still supported for now.
    Source code(tar.gz)
    Source code(zip)
  • v35.2.0(Apr 14, 2022)

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.1.0(Mar 22, 2022)

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v35.0.1(Mar 15, 2022)

  • v35.0.0(Mar 9, 2022)

    Major Changes

    • #1910 e1e8d478 Thanks @colebemis! - ActionList2 exported types are now prefixed with ActionList:

      ListProps → ActionListProps
      GroupProps → ActionListGroupProps
      ItemProps → ActionListItemProps
      DescriptionProps → ActionListDescriptionProps
      LeadingVisualProps → ActionListLeadingVisualProps,
      TrailingVisualProps → ActionListTrailingVisualProps
      

      ActionMenu2 exported types are now prefixed with ActionMenu:

      MenuButtonProps → ActionMenuButtonProps
      MenuAnchorProps → ActionMenuAnchorProps
      
    • #1910 e1e8d478 Thanks @colebemis! -

      ActionList

      ActionList has been rewritten with a composable API, design updates and accessibility fixes.

      See full list of props and examples: https://primer.style/react/ActionList

      Before (v34) After (v35)
      <ActionList
        items={[
          {text: 'New file'},
          {text: 'Copy link'},
          {text: 'Edit file'},
          ActionList.Divider,
          {text: 'Delete file', variant: 'danger'}
        ]}
      />
      
      <ActionList>
        <ActionList.Item>New file</ActionList.Item>
        <ActionList.Item>Copy link</ActionList.Item>
        <ActionList.Item>Edit file</ActionList.Item>
        <ActionList.Divider />
        <ActionList.Item variant="danger">Delete file</ActionList.Item>
      </ActionList>
      
      <ActionList
        showItemDividers
        items={[
          {
            key: '0',
            leadingVisual: LinkIcon,
            text: 'github/primer'
          },
          {
            key: '1',
            leadingVisual: () => <Avatar src="https://github.com/mona.png" />,
            text: 'mona',
            description: 'Monalisa Octocat',
            descriptionVariant: 'block'
          },
          {
            key: '2',
            leadingVisual: GearIcon,
            text: 'View Settings',
            trailingVisual: ArrowRightIcon
          }
        ]}
      />
      
      <ActionList showDividers>
        <ActionList.Item>
          <ActionList.LeadingVisual>
            <LinkIcon />
          </ActionList.LeadingVisual>
          github/primer
        </ActionList.Item>
        <ActionList.Item>
          <ActionList.LeadingVisual>
            <Avatar src="https://github.com/mona.png" />
          </ActionList.LeadingVisual>
          mona
          <ActionList.Description variant="block">Monalisa Octocat</ActionList.Description>
        </ActionList.Item>
        <ActionList.Item>
          <ActionList.LeadingVisual>
            <GearIcon />
          </ActionList.LeadingVisual>
          View settings
          <ActionList.TrailingVisual>
            <ArrowRightIcon />
          </ActionList.TrailingVisual>
        </ActionList.Item>
      </ActionList>
      
      <ActionList
        groupMetadata={[
          {groupId: '0', header: {title: 'Live query'}},
          {groupId: '1', header: {title: 'Layout'}}
        ]}
        items={[
          {key: '0', text: 'repo:github/github', groupId: '0'},
          {key: '1', text: 'Table', groupId: '1'},
          {key: '2', text: 'Board', groupId: '1'},
          {key: '3', text: 'View settings'}
        ]}
      />
      
      <ActionList>
        <ActionList.Group title="Live query">
          <ActionList.Item>repo:github/github</ActionList.Item>
        </ActionList.Group>
        <ActionList.Divider />
      
        <ActionList.Group title="Layout">
          <ActionList.Item>Table</ActionList.Item>
          <ActionList.Item>Board Description</ActionList.Item>
        </ActionList.Group>
        <ActionList.Divider />
      
        <ActionList.Item>View settings</ActionList.Item>
      </ActionList>
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {ActionList} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

    • #1910 e1e8d478 Thanks @colebemis! -

      ActionMenu

      ActionMenu has been rewritten with a composable API, design updates and accessibility fixes.

      See full list of props and examples: https://primer.style/react/ActionMenu

      Main changes:

      1. Instead of using items prop, use ActionList inside ActionMenu
      2. Instead of using anchorContent on ActionMenu, use ActionMenu.Button with children
      3. Instead of using onAction prop on ActionMenu, use onSelect prop on ActionList.Item
      4. Instead of using groupMetadata on ActionMenu, use ActionList.Group
      5. Instead of overlayProps on ActionMenu, use ActionMenu.Overlay
      Before (v34) After (v35)
      <ActionMenu
        anchorContent="Menu"
        onAction={fn}
        items={[
          {text: 'New file'},
          {text: 'Copy link'},
          {text: 'Edit file'},
          ActionMenu.Divider,
          {text: 'Delete file', variant: 'danger'}
        ]}
        overlayProps={{width: 'small'}}
      />
      
      <ActionMenu>
        <ActionMenu.Button>Menu</ActionMenu.Button>
        <ActionMenu.Overlay width="small">
          <ActionList>
            <ActionList.Item onSelect={fn}>New file</ActionList.Item>
            <ActionList.Item>Copy link</ActionList.Item>
            <ActionList.Item>Edit file</ActionList.Item>
            <ActionList.Divider />
            <ActionList.Item variant="danger">Delete file</ActionList.Item>
          </ActionList>
        </ActionMenu.Overlay>
      </ActionMenu>
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {ActionMenu} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

    • #1910 e1e8d478 Thanks @colebemis! -

      DropdownMenu

      DropdownMenu has been deprecated in favor of ActionMenu with ActionList

      See example with selection: https://primer.style/react/ActionMenu#with-selection

      Migration guide:

      1. Instead of using items prop, use ActionList inside ActionMenu
      2. Use selectionVariant="single" on ActionList to set the right semantics for selection
      3. Instead of using selectedItem prop, use selected prop on ActionList.Item
      4. Instead of using renderAnchor and placeholder props on DropdownMenu, use ActionMenu.Button or ActionMenu.Anchor
      5. Instead of using onChange prop on DropdownMenu, use onSelect prop on ActionList.Item
      6. Instead of using groupMetadata on DropdownMenu, use ActionList.Group
      7. Instead of overlayProps on DropdownMenu, use ActionMenu.Overlay
      Before (v34) After (v35)
      const fieldTypes = [
        {key: 0, text: 'Text'},
        {key: 1, text: 'Number'},
        {key: 3, text: 'Date'},
        {key: 4, text: 'Single select'},
        {key: 5, text: 'Iteration'}
      ]
      
      const Example = () => {
        const [selectedType, setSelectedType] = React.useState()
      
        return (
          <DropdownMenu
            renderAnchor={({children, ...anchorProps}) => (
              <ButtonInvisible {...anchorProps}>
                {children} <GearIcon />
              </ButtonInvisible>
            )}
            placeholder="Field type"
            items={fieldTypes}
            selectedItem={selectedType}
            onChange={setSelectedType}
            overlayProps={{width: 'medium'}}
          />
        )
      }
      
      const fieldTypes = [
        {id: 0, text: 'Text'},
        {id: 1, text: 'Number'},
        {id: 3, text: 'Date'},
        {id: 4, text: 'Single select'},
        {id: 5, text: 'Iteration'}
      ]
      
      const Example = () => {
        const [selectedType, setSelectedType] = React.useState()
      
        render(
          <ActionMenu>
            <ActionMenu.Button aria-label="Select field type">{selectedType.name || 'Field type'}</ActionMenu.Button>
            <ActionMenu.Overlay width="medium">
              <ActionList selectionVariant="single">
                {fieldTypes.map(type => (
                  <ActionList.Item
                    key={type.id}
                    selected={type.id === selectedType.id}
                    onSelect={() => setSelectedType(type)}
                  >
                    {type.name}
                  </ActionList.Item>
                ))}
              </ActionList>
            </ActionMenu.Overlay>
          </ActionMenu>
        )
      }
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {DropdownMenu} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

      drafts/DropdownMenu2

      DropdownMenu2 has been removed in favor of ActionMenu with ActionList

    • #1910 e1e8d478 Thanks @colebemis! -

      Label

      The Label component's API and visual design have been updated to be consistent with its counterpart in Primer ViewComponents' Label component.

      Major changes in the new Label component:

      • No more medium size - only small and large
      • Labels are outlined by default, so the outline prop has been removed
      • Custom text and background colors are discouraged, but still possible via the sx prop

      If you were using the Label component to render issue/PR labels, use the IssueLabelToken component instead.

      Before (v34) After (v35)
      import {Label} from '@primer/react'
      
      function Example() {
        return (
          <>
            <Label outline>default</Label>
            <Label variant="small" outline sx={{borderColor: 'danger.emphasis', color: 'danger.fg'}}>
              danger
            </Label>
          </>
        )
      }
      
      import {Label} from '@primer/react'
      
      function Example() {
        return (
          <>
            <Label>default</Label>
            <Label size="small" variant="danger">
              danger
            </Label>
          </>
        )
      }
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {Label} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

    • #1910 e1e8d478 Thanks @colebemis! -

      Button

      Before v35, Button was a set of seven independent components. In v35, we've simplified the Button API.

      Button variants

      We now support a variant property which takes values primary, invisible, outline and danger

      Before (v34) After (v35)
      import {ButtonPrimary, ButtonInvisible, ButtonOutline, ButtonDanger} from '@primer/react'
      
      function Example() {
        return (
          <>
            <ButtonPrimary>Primary Button</ButtonPrimary>
            <ButtonInvisible>Invisible Button</ButtonInvisible>
            <ButtonOutline>Outline Button</ButtonOutline>
            <ButtonDanger>Danger Button</ButtonDanger>
          </>
        )
      }
      
      import {Button} from '@primer/react'
      
      function Example() {
        return (
          <>
            <Button variant="primary">Primary Button</Button>
            <Button variant="invisible">Invisible Button</Button>
            <Button variant="outline">Outline Button</Button>
            <Button variant="danger">Danger Button</Button>
          </>
        )
      }
      

      Leading and trailing icons

      Previously including icons inside buttons required a lot of custom styling. In the new Button component, we now support first-class leadingIcon and trailingIcon props:

      Before (v34) After (v35)
      <Button>
        <SearchIcon />
        Search
      </Button>
      
      <Button leadingIcon={SearchIcon}>Search</Button>
      

      Icon buttons

      Icon-only buttons are common in many applications. We now have a component designed for this use-case:

      Before (v34) After (v35)
      <Button>
        <XIcon />
      </Button>
      
      <IconButton aria-label="Close button" icon={XIcon} />
      

      Size property

      Previously, we used a variant prop to set the size of buttons. We now have a prop called size which is more semantically correct.

      Before (v34) After (v35)
      <Button variant="small">Small button</Button>
      
      <Button size="small">Small button</Button>
      
    • #1910 e1e8d478 Thanks @colebemis! -

      ChoiceFieldset

      The CheckboxGroup and RadioGroup components are replacing the ChoiceFieldset component.

      CheckboxGroup and RadioGroup have the ability to render contextual content with your fieldset: labels, validation statuses, captions. They also handle the ARIA attributes that make the form controls accessible to assistive technology.

      Before (v34) After (v35)
      import {ChoiceFieldset} from '@primer/react'
      
      function Example() {
        return (
          <>
            {/* Multi-select */}
            <ChoiceFieldset>
              <ChoiceFieldset.Legend>Preferred Primer component interface</ChoiceFieldset.Legend>
              <ChoiceFieldset.List selectionVariant="multiple">
                <ChoiceFieldset.Item value="figma">Figma library</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="css">Primer CSS</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="react">Primer React components</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="viewcomponents">Primer ViewComponents</ChoiceFieldset.Item>
              </ChoiceFieldset.List>
            </ChoiceFieldset>
      
            {/* Single select */}
            <ChoiceFieldset>
              <ChoiceFieldset.Legend>Preferred Primer component interface</ChoiceFieldset.Legend>
              <ChoiceFieldset.List>
                <ChoiceFieldset.Item value="figma">Figma library</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="css">Primer CSS</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="react">Primer React components</ChoiceFieldset.Item>
                <ChoiceFieldset.Item value="viewcomponents">Primer ViewComponents</ChoiceFieldset.Item>
              </ChoiceFieldset.List>
            </ChoiceFieldset>
          </>
        )
      }
      
      import {CheckboxGroup, RadioGroup, FormControl, Checkbox, Radio} from '@primer/react'
      
      function Example() {
        return (
          <>
            {/* Multi-select */}
            <CheckboxGroup>
              <CheckboxGroup.Label>Preferred Primer component interface</CheckboxGroup.Label>
              <FormControl>
                <Checkbox value="figma" />
                <FormControl.Label>Figma</FormControl.Label>
              </FormControl>
              <FormControl>
                <Checkbox value="css" />
                <FormControl.Label>CSS</FormControl.Label>
              </FormControl>
              <FormControl>
                <Checkbox value="react" />
                <FormControl.Label>Primer React components</FormControl.Label>
              </FormControl>
              <FormControl>
                <Checkbox value="viewcomponents" />
                <FormControl.Label>Primer ViewComponents</FormControl.Label>
              </FormControl>
            </CheckboxGroup>
      
            {/* Single select */}
            <RadioGroup name="preferred-primer">
              <RadioGroup.Label>Preferred Primer component interface</RadioGroup.Label>
              <FormControl>
                <Radio value="figma" />
                <FormControl.Label>Figma</FormControl.Label>
              </FormControl>
              <FormControl>
                <Radio value="css" />
                <FormControl.Label>CSS</FormControl.Label>
              </FormControl>
              <FormControl>
                <Radio value="react" />
                <FormControl.Label>Primer React components</FormControl.Label>
              </FormControl>
              <FormControl>
                <Radio value="viewcomponents" />
                <FormControl.Label>Primer ViewComponents</FormControl.Label>
              </FormControl>
            </RadioGroup>
          </>
        )
      }
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {ChoiceFieldset} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

    • #1910 e1e8d478 Thanks @colebemis! -

      PageLayout

      PageLayout is being graduated from the drafts bundle to the main bundle.

      To upgrade, rewrite your imports accordingly:

      - import {PageLayout} from '@primer/react/drafts'
      + import {PageLayout} from '@primer/react'
      
    • #1910 e1e8d478 Thanks @colebemis! -

      FormGroup, InputField, ChoiceInputField

      The FormControl component is replacing the FormGroup, InputField, and ChoiceInputField components. It has the ability to render contextual content with your inputs: labels, validation statuses, captions. It also handles the ARIA attributes that make the form controls accessible to assistive technology.

      Before (v34) After (v35)
      import {FormControl, Checkbox, TextInput} from '@primer/react'
      
      function Example() {
        return (
          <>
            <FormGroup>
              <FormGroup.Label htmlFor="example-text">Example text</FormGroup.Label>
              <TextInput id="example-text" />
            </FormGroup>
            {/* OR */}
            <InputField>
              <InputField.Label>Example text</InputField.Label>
              <TextInput />
            </InputField>
            {/* OR */}
            <ChoiceInputField>
              <ChoiceInputField.Label>Example text</ChoiceInputField.Label>
              <Checkbox />
            </ChoiceInputField>
          </>
        )
      }
      
      import {FormGroup, TextInput} from '@primer/react'
      
      function Example() {
        return (
          <>
            <FormControl>
              <FormControl.Label>Example text</FormControl.Label>
              <TextInput />
            </FormControl>
            {/* OR */}
            <FormControl>
              <FormControl.Label>Example text</FormControl.Label>
              <Checkbox />
            </FormControl>
          </>
        )
      }
      
      import {InputField, TextInput} from '@primer/react'
      
      function Example() {
        return (
          <InputField>
            <InputField.Label>Example text</InputField.Label>
            <TextInput />
          </InputField>
        )
      }
      
      import {FormControl, TextInput} from '@primer/react'
      
      function Example() {
        return (
          <FormControl>
            <FormControl.Label>Example text</FormControl.Label>
            <TextInput />
          </FormControl>
        )
      }
      

      To continue to use the deprecated API for now, change the import path to @primer/react/deprecated:

      import {FormGroup, ChoiceInputField, InputField} from '@primer/react/deprecated'
      

      You can use the one-time codemod to change your import statements automatically.

    • #1910 e1e8d478 Thanks @colebemis! -

      SelectMenu

      ⚠️ SelectMenu has been deprecated. Please use ActionMenu instead.

      Before After
      <SelectMenu>
        <Button as="summary">Projects</Button>
        <SelectMenu.Modal>
          <SelectMenu.Header>Projects</SelectMenu.Header>
          <SelectMenu.List>
            <SelectMenu.Item href="#">Primer React bugs</SelectMenu.Item>
            <SelectMenu.Item href="#">Primer React roadmap</SelectMenu.Item>
            <SelectMenu.Item href="#">Project 3</SelectMenu.Item>
            <SelectMenu.Item href="#">Project 4</SelectMenu.Item>
          </SelectMenu.List>
        </SelectMenu.Modal>
      </SelectMenu>
      
      <ActionMenu>
        <ActionMenu.Button>Projects</ActionMenu.Button>
        <ActionMenu.Overlay>
          <ActionList showDividers>
            <ActionList.Group title="Projects">
              <ActionList.Item>Primer React bugs</ActionList.Item>
              <ActionList.Item>Primer React roadmap</ActionList.Item>
              <ActionList.Item>Project three</ActionList.Item>
              <ActionList.Item>Project four</ActionList.Item>
            </ActionList.Group>
          </ActionList>
        </ActionMenu.Overlay>
      </ActionMenu>
      

      See https://primer.style/react/ActionMenu for more migration examples.

      Dropdown

      ⚠️ Dropdown has been deprecated. Please use ActionMenu instead.

      Before After
      const fieldTypes = [
        {leadingVisual: TypographyIcon, text: 'Text'},
        {leadingVisual: NumberIcon, text: 'Number'}
      ]
      
      const Example = () => {
        const [selectedItem, setSelectedItem] = React.useState()
      
        return (
          <DropdownMenu
            renderAnchor={({children, ...anchorProps}) => <ButtonInvisible {...anchorProps}>{children}</ButtonInvisible>}
            placeholder="Select a field type"
            items={fieldTypes}
            selectedItem={selectedItem}
            onChange={() => setSelectedIndex(index)}
          />
        )
      }
      
      const fieldTypes = [
        {icon: <TypographyIcon />, name: 'Text'},
        {icon: <NumberIcon />, name: 'Number'}
      ]
      
      const Example = () => {
        const [selectedItem, setSelectedItem] = React.useState()
      
        return (
          <ActionMenu>
            <ActionMenu.Button>{selectedItem ? selectedItem.name : 'Select a field type'}</ActionMenu.Button>
            <ActionMenu.Overlay>
              <ActionList selectionVariant="single">
                {fieldTypes.map(field => (
                  <ActionList.Item onSelect={() => setSelectedItem(field)} key={field.name}>
                    <ActionList.LeadingVisual>{field.icon}</ActionList.LeadingVisual>
                    {field.name}
                  </ActionList.Item>
                ))}
              </ActionList>
            </ActionMenu.Overlay>
          </ActionMenu>
        )
      }
      

      See https://primer.style/react/ActionMenu for more migration examples.

      Flex

      ⚠️ Flex has been deprecated. Please use Box instead.

      Before After
      <Flex flexWrap="nowrap">
        <Box p={3} color="fg.onEmphasis" bg="accent.emphasis">
          Item 1
        </Box>
      </Flex>
      
      <Box display="flex" flexWrap="nowrap">
        <Box p={3} color="fg.onEmphasis" bg="accent.emphasis">
          Item 1
        </Box>
      </Box>
      

      Grid

      ⚠️ Grid has been deprecated. Please use Box instead.

      Before After
      <Grid gridTemplateColumns="repeat(2, auto)" gridGap={3}>
        <Box p={3} color="fg.onEmphasis" bg="accent.emphasis">
          1
        </Box>
        <Box p={3} color="fg.onEmphasis" bg="attention.emphasis">
          2
        </Box>
      </Grid>
      
      <Box display="grid" gridTemplateColumns="repeat(2, auto)" gridGap={3}>
        <Box p={3} color="fg.onEmphasis" bg="accent.emphasis">
          1
        </Box>
        <Box p={3} color="fg.onEmphasis" bg="attention.emphasis">
          2
        </Box>
      </Box>
      

      BorderBox

      ⚠️ BorderBox has been deprecated. Please use Box instead.

      Before After
      <BorderBox>Item 1</BorderBox>
      
      <Box borderWidth="1px" borderStyle="solid" borderColor="border.default" borderRadius={2}>
        Item 1
      </Box>
      

      Position

      ⚠️ Position has been deprecated. Please use Box instead.

      Before After
      <>
        <Position position="absolute">...</Position>
        <Absolute>...</Absolute>
        <Relative>...</Relative>
        <Fixed>...</Fixed>
        <Sticky>...</Sticky>
      </>
      
      <>
        <Box position="absolute">...</Box>
        <Box position="absolute">...</Box>
        <Box position="relative">...</Box>
        <Box position="fixed">...</Box>
        <Box position="sticky">...</Box>
      </>
      

    Minor Changes

    Patch Changes

    • #1910 e1e8d478 Thanks @colebemis! - ActionMenu.Button: Fix spacing between text and caret

    • #1910 e1e8d478 Thanks @colebemis! - - Update styles for default variant of Button's active state

      • Use active state for Button when it is used to open an Overlay
    • #1910 e1e8d478 Thanks @colebemis! - Surfaced the following components and hooks from the root index:

      • Portal
      • AnchoredOverlay
      • useFocusTrap
      • useFocusZone (and types)
      • sx (and types)
      • ConfirmationDialogProps

      These exports can now be imported from the root index, rather than from their nested subfolders.

      E.g.

      - import { ConfirmationDialogProps } from '@primer/react/lib-esm/Dialog/ConfirmationDialog';
      + import { ConfirmationDialogProps } from '@primer/react';
      
    Source code(tar.gz)
    Source code(zip)
  • v34.7.1(Mar 9, 2022)

  • v34.7.0(Mar 7, 2022)

  • v34.6.0(Feb 23, 2022)

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v34.5.0(Feb 10, 2022)

    Minor Changes

    • #1831 96473f39 Thanks @mperrotti! - Makes validation styling available for Select and TextInputWithTokens

    • #1836 7e8ae653 Thanks @mperrotti! - Introduces FormControl component. The FormControl component combines the functionality of InputField and ChoiceInputField, and will replace FormGroup, InputField, and ChoiceInputField.

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
  • v34.4.0(Feb 8, 2022)

    Minor Changes

    Patch Changes

    • #1824 4eab65e5 Thanks @siddharthkp! - Overlay: Attach escape handler to overlay container instead of document to fix stopPropagation

    • #1840 1c4786c7 Thanks @jclem! - Set Node.js and npm versions to ">=12" and ">=7", respectively, in package.json manifests, and update package-lock.json files accordingly.

    • #1828 6a695bdc Thanks @siddharthkp! - ActionMenu2 + DropdownMenu2: A keyboard user will be able to wrap through options

    • #1810 35ad7084 Thanks @siddharthkp! - ActionMenu2 + DropdownMenu2: Focus the correct element when Menu is opened with keyboard. See detailed spec.

      • ArrowDown | Space | Enter: first element
      • ArrowUp: last element
    • #1842 11011f55 Thanks @jclem! - Allow KeyPaths type to accept any type in order to remove need for // @ts-ignore internally.

    • #1820 50c7bfaa Thanks @colebemis! - Add draft PageLayout component

    Source code(tar.gz)
    Source code(zip)
  • v34.3.0(Jan 26, 2022)

    Minor Changes

    Patch Changes

    • #1759 493c6ea1 Thanks @siddharthkp! - AnchoredOverlay: Add support for passing an id to the anchor. Remove unnecessary aria-labelledby on anchor. ActionMenu v2: Add aria-labelledby for ActionList

    • #1779 2630800d Thanks @siddharthkp! - ActionMenu v2: ActionMenu.Button now uses Button v2

    • #1735 8ff114b1 Thanks @siddharthkp! - Add composable DropdownMenu to @primer/components/drafts

    • #1814 384c3756 Thanks @pksjce! - Upgrade @primer/behaviors

    • #1804 aa09ed79 Thanks @rezrah! - Fixes bug in PointerBox component where caret doesn't inherit correct styling. Backwards compataible with previous API.

    Source code(tar.gz)
    Source code(zip)
  • v34.2.0(Jan 13, 2022)

    Minor Changes

    Patch Changes

    Source code(tar.gz)
    Source code(zip)
Owner
Primer
Components, design guidelines, and tooling for GitHub's design system.
Primer
Ember implementation of Google's Material Design

No longer maintained This project is no longer maintained. For an up-to-date material design project, please use Ember Paper. Ember-material-design Th

Mike Wilson 121 Mar 1, 2022
ConcreteUI is a ~neubrutalist~ design system 🧱

ConcreteUI ?? Very early stage ConcreteUI is a neubrutalist design system with inspiration from this medium article. Getting Started Make sure you hav

Daniel Moura 7 Dec 13, 2022
A frontend Framework for building B2B applications running in the browser on top of REST/GraphQL APIs, using ES6, React and Material Design

react-admin A frontend Framework for building data-driven applications running in the browser on top of REST/GraphQL APIs, using ES6, React and Materi

marmelab 21.2k Dec 30, 2022
This command line helps you create components, pages and even redux implementation for your react project

react-help-create This command line helps you create components, pages and even redux implementation for your react project. How to install it? To ins

Omar 27 Dec 10, 2022
KochSnowFlake - implementation of Koch Snowflake with React+ TS

Koch Snowflake if you just want to play with it, follow, FOLLOW THIS LINK if you are curios about math of this project, FOLLOW THIS LINK installation

Mahyar 1 Mar 13, 2022
Plock is a responsive masonry layout implementation for React. Very simple to use and easy to understand.

About Plock ?? Plock is a responsive masonry layout implementation for React. Very simple to use and easy to understand. Can I see a demo? ?? The demo

Renato Pozzi 130 Dec 9, 2022
An implementation of React v15.x that optimizes for small script size

react-lite Introduction react-lite is an implementation of React that optimizes for small script size. Note: react-lite dose not support React v16.x n

工业聚 1.7k Dec 10, 2022
This is a Javascript / React implementation of Discord's OverlappingPanels

Overlapping Panels Gestures-driven navigation UI for React.js This is a Javascript / React implementation of Discord's OverlappingPanels. Gesture-base

Paul Makles 5 Feb 18, 2022
✂ Multiple scenes, one canvas! WebGL Scissoring implementation for React Three Fiber.

react-three-scissor Multiple scenes, one canvas! WebGL Scissoring implementation for React Three Fiber. scissor lets you render an infinite number of

Poimandres 79 Dec 28, 2022
A free book that talks about design patterns/techniques used while developing with React.

React in patterns ?? A free book that talks about design patterns/techniques used while developing with React. Book GitBook Web PDF Mobi ePub Translat

Krasimir Tsonev 12.3k Jan 7, 2023
A set of React components implementing Google's Material Design specification with the power of CSS Modules

React Toolbox is a set of React components that implement Google's Material Design specification. It's powered by CSS Modules and harmoniously integra

React Toolbox 8.7k Dec 30, 2022
A React Component library implementing the Base design language

Base Web React Components Base is a design system comprised of modern, responsive, living components. Base Web is the React implementation of Base. Us

Uber Open Source 8.1k Dec 29, 2022
Starter Antd 4.0 Admin App Mern( Node.js / React / Redux / Ant Design ) Crud & Auth , Dashboard

Starter Antd Admin (Crud & auth) Mern App (Express.js / React / Redux / MongoDB) App built for DigitalOcean MongoDB Hackathon CRM Starter Mern Antd Ad

Salah Eddine Lalami 208 Jan 8, 2023
Hacker-news-with-react - 👾 Consuming the hacker news api, i created a more modern design for than the current site.

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

João Thomaz 1 Jan 3, 2022
Accessible, unstyled, open-sourced, and fully functional react component library for building design systems

DORAI UI Accessible, unstyled, open-sourced and fully functional react component library for building design systems Documentation site coming soon St

Fakorede Boluwatife 38 Dec 30, 2022
This solution aims to simplify the implementation of login using SPID or similar services, such as CIE and eIDAS

This solution aims to simplify the implementation of login using SPID or similar services, such as CIE and eIDAS. It supports both the use of ADFS and B2C as identity federators.

Microsoft 19 Dec 2, 2022
Recoil is an experimental state management library for React apps. It provides several capabilities that are difficult to achieve with React alone, while being compatible with the newest features of React.

Recoil · Recoil is an experimental set of utilities for state management with React. Please see the website: https://recoiljs.org Installation The Rec

Facebook Experimental 18.2k Jan 8, 2023
:atom_symbol: React primitive UI components built with styled-system.

Rebass React primitive UI components built with Styled System. https://rebassjs.org npm i rebass Getting Started import React from 'react' import { Bo

Rebass 7.9k Dec 31, 2022
An example of a schema-based form system for React.

React Advanced Form An example of a schema-based form system in React. Define your schema, and pass it into the form. Supports basic conditional schem

Tania Rascia 111 Dec 31, 2022