Giter VIP home page Giter VIP logo

bumbag-ui's Introduction

bumbag-ui's People

Contributors

agustif avatar benjenkinson avatar chrischuck avatar danielagattoni avatar darksmile92 avatar daveols avatar dependabot[bot] avatar diegohaz avatar emgoto avatar handlebauer avatar hastebrot avatar hazem3500 avatar joe-bell avatar joemaffei avatar jordanoverbye avatar joshball avatar joshuafsharp avatar jxom avatar magicmark avatar markwilson avatar maxmorlocke avatar michaeltym avatar nchlswhttkr avatar nejcr avatar samantha-wong avatar shannonrothe avatar shawntax avatar terencehuynh avatar thepenskefile avatar tomanagle avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar

bumbag-ui's Issues

Typescript: Support `use` component prop types on the base component

At the moment, if we try to compose two components via the use prop. The component specified via use will not spread its TS types on the root component. Thus, the following will produce a typescript error on the href prop:

<Button use={Link} href="https://example.com">Go to Example</Button>

Ref does not work on custom components created with applyTheme

React refs do not seem to work correctly on custom components created with applyTheme.
This seems to be because they are a functional component and they don't correctly forwardRef?

I get this error:

Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

To Reproduce

const CustomButton = applyTheme(Button, {
  styles: {
    base: {
      minHeight: "unset",
      whiteSpace: `nowrap`,
    },
  },
  defaultProps: {
    variant: "ghost",
  },
});

const App = () => {
  const buttonRef = useRef(null);
  const handleClick = () => {
    console.log(buttonRef.current) // should be defined
  }
  return (
    <CustomButton onClick={handleClick} ref={buttonRef}>
      Click
    </CustomButton>
  );
};

Enhance typescript type for better autocompletion.

Is your feature request related to a problem? Please describe.

Multiple type definitions of Component props.

For example onChange props of Input component

Screenshot from 2020-08-12 14-08-33

The Input props:
export type InputProps = BoxProps & LocalInputProps;
There are two type of onChange from BoxProps and LocalInputProps

This will make typescript confuse about autocompletion.
Screenshot from 2020-08-12 23-24-29

Describe the solution you'd like
Remove duplication type from inheritance props (BoxProps)

type IntersectionType = keyof LocalInputProps & keyof BoxProps;

export type InputProps = Omit<BoxProps, IntersectionType> & LocalInputProps;

Result:
Screenshot from 2020-08-12 23-23-31

Additional context
Another issue related to the literal string union ("circle").

Screenshot from 2020-08-12 23-44-05

There are no options for Intellisense:
Screenshot from 2020-08-12 23-45-41

Solution and result:
Use simple hack from community

Screenshot from 2020-08-12 23-56-46

Screenshot from 2020-08-12 23-56-28

Add support for HTML5 required attribute for Input component where isRequired prop is set to true

On Bumbag's input component, there is a prop called isRequired, which seems like when set, will set the relevant attributes for marking an input as required, with accessibility taken into consideration. At present, the input component only sets the aria-required and aria-invalid attributes, but recently HTML5 have introduced a new attribute called required.

MDN articles below about aria-required and required both suggests that while the required attribute is meant to serve the same purpose as aria-required, there is no harm putting both just to cover most user agents.

MDN aria-required

Assistive technology should inform the user that the form control in mandatory based on the required attribute, but adding aria-required="true" doesn't hurt, in case the browser / screen reader combination does not support required yet.

MDN input required attribute

Assistive technology should inform the user that the form control in mandatory based on the required attribute, but adding aria-required="true" doesn't hurt, in case the browser / screen reader combination does not support required yet.

This Feb 2019 article by Paciello Group about Accessibility support of required attribute on different devices provides great insight about the support of the required attribute and some recommendations on how to use them.

Should we add the required attribute for when isRequired prop is set for input components, and (since I'm not an accessibility export), how do we juggle the three things to help ensure that we have greater accessibility coverage?

Alternatively, the current workaround is to set the isRequired and required attribute onto the input, which works fine, just that the property isRequired is not native to html input and seems redundant to tell the input component that it is required and still have to set myself a native HTML5 required attribute.

<Input isRequired="true" required/>

Other references:
Stackoverflow discussion

Love to have a discussion and happy to do the change PR if someone is willing to provide some context guidance.

`SelectMenu โ€” hasTags` lets you select the same tag twice

When using SelectMenu with hasTags, you can select the same tag twice, and it will be added to the 'value' state variable where user selected tags are stored.

Example:
apw-cat local -  2020-08-12 at 2 30 51 AM

With a Tag Selection Component, it should only allow you to add each option to your selection once to prevent confusion from a user perspective. Adding a duplicate tag also causes a react dom warning, because you end up with two children (the selected tags) that share an identical key.

React-dom warning (truncated):

[Error] Warning: Encountered two children with the same key, `3`. 
Keys should be unique so that components maintain their identity across updates.
Non-unique keys may cause children to be duplicated and/or omitted โ€” 
the behavior is unsupported and could change in a future version.
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Set)
    in Set (created by SelectMenuTags)
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Box)
    in Box (created by SelectMenuTags)
    in SelectMenuTags
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by DropdownMenu.Popover)
    in DropdownMenu.Popover
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by SelectMenu)
    in SelectMenu (at Tags.js:19)
    in Tags (at pages/index.js:16)
    in div (created by ForwardRef(Box))

Expected behavior

A tag should only be allowed to be selected once

Possible Solution

Use a set for storing the selected tags? There may be some gotchas I'm missing, but it might work.

Device information (please complete the following information):

  • Device: Macbook Pro, 2015
  • OS, version: macOS 10.15.6
  • Browser, version: Safari 14 TP, Firefox

SwitchGroup Horizontal alignment

Describe the bug

The last switch in the SwitchGroup isn't aligned correctly when the orientation is horizontal

To Reproduce

playroom: link

Expected behavior

All switches to be aligned when the orientation is horizontal

The Dialog/Modal reports an error when used with next.js

Describe the bug

The Dialog/Modal reports an error when used with next.js.

To Reproduce

  1. Go to https://y92q9.sse.codesandbox.io/
  2. Open Chrome DevTools Console
  3. See error (Screenshots below)

Code: https://codesandbox.io/s/bumbag-dialog-issue-y92q9?file=/components/TestDialog.tsx

import React from "react";
import { Modal, Button, Card, Box } from "bumbag";

const TestDialog = () => {
  return (
    <Modal.State>
      <Modal.Disclosure use={Button}>Open modal</Modal.Disclosure>
      <Modal>
        <Card>
          <Box>Hello world</Box>
          <Modal.Disclosure use={Button}>Close</Modal.Disclosure>
        </Card>
      </Modal>
    </Modal.State>
  );
};

export default TestDialog;

Expected behavior

Screenshots

Device information (please complete the following information):

  • Device: Macbook Pro
  • OS, version: macOS 10.15.6
  • Browser, version: Chrome 84.0.4147.125

Additional context

Type error with PageWithHeader sticky.

Thanks for keeping the great work, I reimplemented on nextjs based on latest docs, when trying out to deploy sticky with PageWithHeaders I get this error.

15:09:09.713 | ./src/pages/index.tsx:5:3
15:09:09.713 | Type error: Type '{ children: (string \| Element)[]; sticky: boolean; header: Element; border: string; overrides: { PageWithHeader: { styles: { base: { minHeight: string; }; }; }; }; }' is not assignable to type 'IntrinsicAttributes & Pick<PageWithHeaderProps, "header" \| "slot" \| "style" \| "title" \| "clipPath" \| "filter" \| "marker" \| "mask" \| ... 769 more ... \| "headerHeight"> & RefAttributes<...>'.
15:09:09.713 | Property 'sticky' does not exist on type 'IntrinsicAttributes & Pick<PageWithHeaderProps, "header" \| "slot" \| "style" \| "title" \| "clipPath" \| "filter" \| "marker" \| "mask" \| ... 769 more ... \| "headerHeight"> &

Maybe I'm doing something wrong?

import { Button, Provider as BumbagProvider , PageWithHeader, TopNav, Image, Box} from 'bumbag';
const MyApp = () => (
  <BumbagProvider>
<PageWithHeader
  sticky
  header={
    <TopNav>
      <TopNav.Section>
        <TopNav.Item href="https://bumbag.style" fontWeight="semibold">
          <Image src="/vercel.svg" height="44px" />
        </TopNav.Item>
        <TopNav.Item href="#">Get started</TopNav.Item>
        <TopNav.Item href="#">Components</TopNav.Item>
      </TopNav.Section>
      <TopNav.Section marginRight="major-2">
        <TopNav.Item>
          <Button variant="ghost" palette="primary">Sign up</Button>
        </TopNav.Item>
        <TopNav.Item>
          <Button palette="primary">Login</Button>
        </TopNav.Item>
      </TopNav.Section>
    </TopNav>
  }
  border="default"
  overrides={{ PageWithHeader: { styles: { base: { minHeight: 'unset' } } } }}
>
  <Box padding="major-2">Hello world</Box> 
</PageWithHeader>
    <Button>
      Hello world!
    </Button>
  </BumbagProvider>
);
export default MyApp

Thanks for any help or pointers you can provide

Switches on Popovers not clickable

Switches on popovers are not clickable via mouse

          <Popover.State placement="bottom-end">
            <Popover.Disclosure use={Button}>

            </Popover.Disclosure>
            <Popover title={user ? `Welcome ${user.displayName}` : 'Login to Continue!'} usePortal>
              <Heading use="h6">User Settings</Heading>
              <Switch
                label={`${isLightMode ? 'Light' : 'Dark'} Mode`}
                checked={isLightMode}
                onClick={() => {
                  if (isLightMode) {
                    setColorMode('dark');
                  } else {
                    setColorMode('light');
                  }
                }}
              />
              <hr />
            </Popover>
          </Popover.State>

image

You can still toggle it via the spacebar when selected

Menu & SelectMenu components scrolls page on focus in Docs

Describe the bug

When clicking on Menu or SelectMenu component the page jumps to a place bottom of the component

To Reproduce

  1. Go to https://bumbag.style/form/select-menu/ or https://bumbag.style/components/menu/
  2. Click on any Menu or selectMenu component

Expected behavior

It should not scroll the page or scrolls to the component, not to the bottom of the page

Screenshots

bug.gif

Device information (please complete the following information):

  • Device: Desktop
  • OS, version: Windows 10
  • Browser, version: Chrome v84.0.4147.135

Creating Vue Version of Bumbag

Is your feature request related to a problem? Please describe.

Is there a way to create Vue version of this project?

I was trying to use Bumbag UI for my Vue application but couldn't find a supported library yet. Is there a way to create one or if it exist can I contribute?

Describe the solution you'd like

I will love to create a Vue version or contribute to any existing one.

Describe alternatives you've considered

Additional context

Rename MenuDisclosure to MenuButton

Autosuggest produces a warning and an error:

MenuDisclosure has been renamed to MenuButton. Using <MenuDisclosure /> will no longer work in future versions.
See https://reakit.io/docs/menu

Uncaught TypeError: element.focus is not a function
onMouseDown Dialog.js:65
useDisclosureRef Dialog.js:69
React 6
unstable_runWithPriority scheduler.development.js:653
React 4
unstable_runWithPriority scheduler.development.js:653
React 25
parcelRequire<["App.js"]< App.js:22
newRequire App.d36a57b6.js:47
parcelRequire App.d36a57b6.js:81
App.d36a57b6.js:120
Dialog.js:65:14
onMouseDown Dialog.js:65
(Async: EventListener.handleEvent)
useDisclosureRef Dialog.js:69
React 6
unstable_runWithPriority scheduler.development.js:653
React 3
performSyncWorkOnRoot self-hosted:1218
flushSyncCallbackQueueImpl React
unstable_runWithPriority scheduler.development.js:653
React 6
bind_applyFunctionN self-hosted:1369
dispatchDiscreteEvent self-hosted:1332
React 19
parcelRequire<["App.js"]< App.js:22
newRequire App.d36a57b6.js:47
parcelRequire App.d36a57b6.js:81
App.d36a57b6.js:120

Tooltip is behind Popover

Describe the bug

I'm using a Tooltip inside a Popover component and the Tooltip is behind the Popover.
Not sure if this is intended - imo, tooltips should have the highest z-index.

To Reproduce

<Popover.State placement="bottom-start" gutter={16}>
  <Popover.Disclosure use={Button}>Click me</Popover.Disclosure>
  <Popover showCloseButton title="Hello">
    <Text.Block color="gray700" fontSize="100">
      Some information
      <Tooltip content="Will appear behind Popup" use="span">
        <Icon marginLeft="minor-1" icon="solid-info-circle" />
      </Tooltip>
    </Text.Block>
  </Popover>
</Popover.State>;

Quick fix

I was able to fix this by overwriting the Tooltip's z-index in theme.ts

const theme = {
  Tooltip: {
    Content: {
      styles: {
        base: {
          // needs to be a string or it won't work
          zIndex: `99999999`,
        },
      },
    },
  },
};

SelectMen && DropdownMenu cause a `react-dom` warning in client side console.

  • SelectMenu and DropdownMenu (this could possibly affect other components), cause react dom to emit a warning message in the browser console.

Sample:

[Error] Warning: Received `false` for a non-boolean attribute `wrap`.

If you want to write it to the DOM, pass a string instead: wrap="false" or wrap={value.toString()}.

If you used to conditionally omit it with wrap={condition && value}, pass wrap={condition ? value : undefined} instead.
    in button (created by ForwardRef(Button))
    in ForwardRef(Button)
    in ForwardRef(Button)
    in Unknown (created by Button)
    in Button (at DropdownTest.js:16)
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by DropdownMenu)
    in DropdownMenu (at DropdownTest.js:6)
    in DropdownTest (at pages/index.js:17)
    in div (created by ForwardRef(Box))
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by PageContent.Wrapper)
    in PageContent.Wrapper (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by PageContent)
    in PageContent (at pages/index.js:9)
    in Index (at _app.js:6)
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Box)
    in Box (created by Provider)
    in PageProvider (created by Provider)
    in ToastProvider (created by Provider)
    in IdProvider (created by Provider)
    in SystemProvider (created by Provider)
    in unstable_IdProvider (created by Provider)
    in Provider (created by Provider)
    in div (created by ColorModeProvider)
    in ColorModeProvider (created by Provider)
    in ThemeProvider (created by Provider)
    in Provider (at _app.js:5)
    in MyApp
    in ErrorBoundary (created by ReactDevOverlay)
    in ReactDevOverlay (created by Container)
    in Container (created by AppContainer)
    in AppContainer
    in Root

I'm using nextjs, but the playroom example for these components also fails to render, so I suspect it's not limited to next projects.

To reproduce, just import SelectMenu from bumbag in a react file, and load the page with dev console open.

Expected behavior

Device information (please complete the following information):

  • Device: Macbook Pro, 2016
  • OS, version: macOS, 10.15.6
  • Browser, version: Safari 14 Preview (also checked firefox).

Simple implementation of SelectMenu

const Tags = () => {
  const [value, setValue] = useState();

  return (
    <SelectMenu
      label='Tags'
      isMultiSelect
      hasTags
      onChange={setValue}
      options={[
        { key: 1, label: 'Apples', value: 'apples' },
        { key: 2, label: 'Bananas', value: 'bananas' },
        { key: 3, label: 'Oranges', value: 'oranges' },
        { key: 4, label: 'Mangos', value: 'mangos' },
      ]}
      placeholder='Select a fruit...'
      value={value}
    />
  );
};

Screenshot of react component tree, with subcomponents of DropdownMenu possessing the wrap prop.

apw-cat local -  2020-08-12 at 2 23 08 AM

My best guess it needs to be omitted from the components props when the component is being implemented.

Thanks!

Menu with options

Is your feature request related to a problem? Please describe.

It isn't clear how or there isn't a component yet to make a menu that contains options that could be selected
menu with options

Describe the solution you'd like

If it's already possible with the current components we could add an example for it in the Docs, If it's not possible with the current set of components we could consider adding a component that handles this use-case.

Problem with Types on IconSets

Using 1.0.0.rc15
Following: https://bumbag.style/components/icon/#usage-via-bumbag-theme

Errror:

yarn run v1.22.4
$ next build
Failed to compile.

./src/pages/_app.tsx:85:23
Type error: Type '{ global: { fontSize: number; css: { root: SerializedStyles; }; }; fonts: { default: string; }; palette: { primary: string; }; breakpoints: { mobile: number; tablet: number; }; Button: { ...; }; Icon: { ...; }; }' is not assignable to type 'ThemeConfig'.
  The types of 'Icon.iconSets' are incompatible between these types.
    Type '{ icons: IconDefinition[]; prefix: string; type: string; }[]' is not assignable to type '{ icons: IconDefinition[]; prefix?: string; type: "font-awesome" | "font-awesome-standalone"; }[]'.
      Type '{ icons: IconDefinition[]; prefix: string; type: string; }' is not assignable to type '{ icons: IconDefinition[]; prefix?: string; type: "font-awesome" | "font-awesome-standalone"; }'.
        Types of property 'type' are incompatible.
          Type 'string' is not assignable to type '"font-awesome" | "font-awesome-standalone"'.

  83 |     const { Component, pageProps } = this.props;
  84 |     return (
> 85 |       <BumbagProvider theme={theme}>
     |                       ^
  86 |                 <style jsx>{`
  87 |           a {
  88 |             margin: 0 10px 0 0;
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

My _app.tsx

import NextApp from 'next/app';
import { Provider as BumbagProvider, css } from 'bumbag';
import { faIgloo, faSearch, faClipboard, faThumbsUp, faHome } from '@fortawesome/free-solid-svg-icons';
import { faAddressBook } from '@fortawesome/free-regular-svg-icons';
import Router from 'next/router'
import Link from 'next/link'
import Head from 'next/head'
import NProgress from 'nprogress'

Router.events.on('routeChangeStart', (url) => {
  console.log(`Loading: ${url}`)
  NProgress.start()
})
Router.events.on('routeChangeComplete', () => NProgress.done())
Router.events.on('routeChangeError', () => NProgress.done())


// svg t="1595278670094" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="611" width="200" height="200">
// import { faHome } from '@fortawesome/free-solid-svg-icons'


const theme = {
  global: {
    fontSize: 18,
    css: {
      root: css`
        html,
        body {
          // background-color: hotpink;
          // color: white;
        }
      .nav-link {
        text-decoration: none;
      }
      .active {
        color: #1890FF;
        text-decoration: wavy underline;
      .icon {
                  // color: blue;
        // text-decoration: wavy underline;
        }
      }

      .active:before {
                // text-decoration: none;

      }
      `
    }
  },
  fonts: {
    default: 'Comic Sans MS'
  },
  palette: {
    primary: '#574FEB',
  },
  breakpoints: {
    mobile: 520,
    tablet: 960
  },
  Button: {
    defaultProps: {
      palette: 'primary'
    }
  },
  Icon: {
    iconSets: [
      {
        icons: [faIgloo, faSearch, faClipboard, faThumbsUp, faHome],
        prefix: 'solid-',
        type: 'font-awesome'
      },
      {
        icons: [faAddressBook],
        prefix: 'regular-',
        type: 'font-awesome'
      }
    ]
  }
}
export default class App extends NextApp {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <BumbagProvider theme={theme}>
                <style jsx>{`
          a {
            margin: 0 10px 0 0;
          }
        `}</style>
              <Head>
        {/* Import CSS for nprogress */}
        <link rel="stylesheet" type="text/css" href="/nprogress.css" />
      </Head>
        <Component {...pageProps} />
      </BumbagProvider>
    );
  }
}

Can't deploy to vercel due build failing bc of this TS error

Autosuggest isn't focus-able after double-clicking on it

Describe the bug

When double clicking Autosuggest it freezes and the user isn't able to search anymore

To Reproduce

  1. Go to https://bumbag.style/form/autosuggest/
  2. Double click on Autosuggest
  3. Try to focus on the input to search

Expected behavior

I should be able to search or focus on the input after double-clicking

Screenshots

issue.gif

Device information (please complete the following information):

  • Device: Desktop
  • OS, version: Windows 10
  • Browser, version: Chrome v84.0.4147.135

Does not work in Gatsby

Reproduction is simple, start a new gatsby starter project then follow the gatsby instructions on the website. Getting this error:

TypeError: theme.modes is undefined
useLocalStorage
node_modules/bumbag/es/utils/useLocalStorage.js:14

  11 | var _useTheme = useTheme(),
  12 |     theme = _useTheme.theme;
  13 | 
> 14 | var isEnabled = theme.modes.enableLocalStorage;
  15 | var get = useCallback(function (key) {
  16 |   if (!isEnabled) return;
  17 | 
  • Bumbag 1.0.2
  • Bumbag Gatsby Plugin 1.02
  • Gatsby 2.24.30

Sections on Autosuggest

Is your feature request related to a problem? Please describe.

Lacking of sections on the Autosuggest componente, like this https://codepen.io/moroshko/pen/qbRNjV

Describe the solution you'd like

Would be nice to have a similar behaviour or even simpler, like tagging each option with a "section" property

Describe alternatives you've considered

Right now I will change the background color depending on the option "type" but putting a header would be ideal

Additional context

I love bumbag

Type definition not available

Type definition is not available -

VSCode Typescript Hint:

Could not find a declaration file for module 'bumbag'. '[PATH_TO_DIR]/node_modules/bumbag/lib/index.js' implicitly has an 'any' type.
Try npm install @types/bumbag if it exists or add a new declaration (.d.ts) file containing declare module 'bumbag';ts(7016)

Error:

error - ./pages/_app.tsx
Attempted import error: 'Provider' is not exported from 'bumbag' (imported as 'BumbagProvider').

Show / Hide above/below

The Show and Hide components seem to respond to a breakpoint above or below the breakpoint supplied.

Open the page at https://bumbag.style/layout/show/ in Chrome. Show Developer Tools with a responsive layout. Change the width of the screen and watch when the message changes. The message should change at a width of 1024px - the desktop breakpoint, as described at https://bumbag.style/breakpoints/ . But, it changes at 768px, the tablet width.

I've seen the same behavior in my own app.

Expected behavior

The message should change at desktop width of 1024px.

Screen Shot 2020-08-23 at 2 39 11 PM

Skeleton Loading

It would be nice to have a Skeleton Loading component added to the component library.
It could have a similar API to Chakra-UI Skeleton Component

I am willing to make a PR implementing that component.

I seeing more then one lack, I need more feature and fixed system

to summarize briefly

  • Components transition property is missing
  • styled to jss (in my opinion)
  • List component
  • Time/Date picker with range and default feature
  • Project based localization library (declare to react-i18next)

If necessary, I can support you by participating in your project.

Note: Meanwhile, my knowledge of English is insufficient. :)

Page Footer

Is your feature request related to a problem? Please describe.

Lack of Fotter component

Describe the solution you'd like

As we have a page with header sounds logic to add a Footer too

Describe alternatives you've considered

Add a footer component by hand

IconButton

Is your feature request related to a problem? Please describe.
N/A

Describe the solution you'd like
A button that just holds an Icon

Describe alternatives you've considered

Additional context

Add example to docs of usage of both PageWithHeader and PageWithSidebar

Is your feature request related to a problem? Please describe.

When trying to use both PageWithHeader and PageWithSidebar, I'm noticing that the sidebar cuts off the bottom pixel of the header:

Playroom example

Screen Shot 2020-08-14 at 10 13 01 pm

Describe the solution you'd like

Maybe I'm missing something completely obvious, but it would be nice to have an example of how to use both successfully (i.e. how the docs site does it).

Adhering to system-UI theme specification

Is your feature request related to a problem? Please describe.

When moving from a library that follows the system-UI theme specification to bumbag we'll need to modify our theme object to conform with bumbag theme object.

Describe the solution you'd like

We can make the theme object of bumbag conform to system-UI and use aliases to make it backward compatible with the old theme specification.

This will allow bumbag-UI to be more interoperable with other libraries and will allow it to leverage tooling that supports system-UI theme specification such as styled-system-figma or fluid-system

Support Controlled Tabs

Is your feature request related to a problem? Please describe.
I need to know which tab is active, so I can do something(fetch data for instance) when tab is in active state

Describe the solution you'd like
If tabs support the controlled state, I guess I can use the selectedId to know which tab is active

Describe alternatives you've considered

  1. provide context store that I can get selectedId and use it to know which tab is active
  2. provide a hook that returns whether tabId is active or not

CSS Warning id's not match on client server.

Trying out nextjs with new isSSR, I get this, am I missing something?

react-dom.development.js?d1ee:88 Warning: Prop `id` did not match. Server: "id-f38874" Client: "id-f71d4d"
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Disclosure.Content)
    in Disclosure.Content
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by PageWithHeader)
    in PageWithHeader (at pages/index.tsx:4)
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Box)
    in Box (created by Provider)
    in PageProvider (created by Provider)
    in ToastProvider (created by Provider)
    in IdProvider (created by Provider)
    in ColorModeProvider (created by Provider)
    in ThemeProvider (created by Provider)
    in Provider (at pages/index.tsx:3)
    in MyApp (at _app.tsx:8)
    in div (created by ForwardRef(Box))
    in ForwardRef(Box)
    in Unknown (created by Box)
    in Box (created by Provider)
    in PageProvider (created by Provider)
    in ToastProvider (created by Provider)
    in IdProvider (created by Provider)
    in div (created by ColorModeProvider)
    in ColorModeProvider (created by Provider)
    in ThemeProvider (created by Provider)
    in Provider (at _app.tsx:7)
    in App
    in ErrorBoundary (created by ReactDevOverlay)
    in ReactDevOverlay (created by Container)
    in Container (created by AppContainer)
    in AppContainer
    in Root

Multiple SelectMenu inputs loadOptions not working as expected

Hi guys,
I've just created a form component with two SelectMenu inputs on it, each one having its own loadOptions

Expeceted behaviour:
Each SelectMenu should load and display its own options.

Actual behaviour:
Only the first SelectMenu loads the options. The getEpisodes callback is not executed and the second SelectMenu "inherits" the options loaded by the first one

Am I doing something wrong?

const Form = (props) => {
  const [character, setCharacter] = useState(null);
  const [episode, setEpisode] = useState(null);

  const getCharacters = React.useCallback(async () => {
    return fetch(`https://rickandmortyapi.com/api/character`)
      .then((res) => res.json())
      .then(({ results }) => ({
        options: results.map((character) => ({
          key: character.id,
          label: character.name,
          value: character
        }))
      }))
      .catch((err) => ({ options: [] }));
  }, []);

  const getEpisodes = React.useCallback(async () => {
    return fetch(`https://rickandmortyapi.com/api/episode`)
      .then((res) => res.json())
      .then(({ results }) => ({
        options: results.map((episode) => ({
          key: episode.id,
          label: episode.name,
          value: episode
        }))
      }))
      .catch((err) => ({ options: [] }));
  }, []);

  return (
    <div style={formStyle}>
      <SelectMenu
        placeholder="Characters"
        value={character}
        onChange={setCharacter}
        loadOptions={getCharacters}
      />
      <SelectMenu
        placeholder="Episodes"
        value={episode}
        onChange={setEpisode}
        loadOptions={getEpisodes}
      />
    </div>
  );
};

Codesandbox
https://codesandbox.io/s/bumbag-select-menu-3zmzo

Submenu support

Is your feature request related to a problem? Please describe.

I was wondering if there's a way to make submenu's from the

components?

Describe the solution you'd like

Would like to have nested submenus where i could select 1 option. Something like this

image

Describe alternatives you've considered

Considered going to Reakit.

Autosuggest in Firefox: Uncaught TypeError: element.focus is not a function

I installed a standard Create React App and used the Autosuggest snippet from the Docs in App.js. I tried the App in Firefox 79 on MacOS 10.15.6, and while it basically works, I get the errors below when I "play around" with the Autosuggest input. It's hard to describe, because I haven't figured out a way to 100% reproduce the problem. But I click in the Autosuggest, click on a suggestion, type something, click outside etc. The only thing that is always triggering the error is a click, be it outside the component, inside the input field or on a suggestion, it doesn't matter. Sometimes the error occurs with the first interactions after loading, sometimes everything is stable for a longer time, but I if this is nothing specific to my setup, I'm sure you will see the error quickly when trying the Autosuggest in Firefox. (Safari and Chromium Edge work fine.)

Below are the tow erros messages, one shows up in the console only, but sometimes (I didn't see any pattern) I get a "full page crash" error with some more details.

Error in the console only

Uncaught TypeError: element.focus is not a function
onMouseDown Dialog.js:65
useDisclosureRef Dialog.js:69
React 6
commitHookEffectListMount
commitPassiveHookEffects
callCallback
invokeGuardedCallbackDev
invokeGuardedCallback
flushPassiveEffectsImpl
unstable_runWithPriority scheduler.development.js:653
React 4
runWithPriority$1
flushPassiveEffects
performSyncWorkOnRoot
flushSyncCallbackQueueImpl
unstable_runWithPriority scheduler.development.js:653
React 6
runWithPriority$1
flushSyncCallbackQueueImpl
flushSyncCallbackQueue
discreteUpdates$1
discreteUpdates
dispatchDiscreteEvent
Dialog.js:65
onMouseDown Dialog.js:65
(Async: EventListener.handleEvent)
useDisclosureRef Dialog.js:69
React 6
commitHookEffectListMount
commitPassiveHookEffects
callCallback
invokeGuardedCallbackDev
invokeGuardedCallback
flushPassiveEffectsImpl
unstable_runWithPriority scheduler.development.js:653
React 3
runWithPriority$1
flushPassiveEffects
performSyncWorkOnRoot
performSyncWorkOnRoot self-hosted:982
flushSyncCallbackQueueImpl React
unstable_runWithPriority scheduler.development.js:653
React 6
runWithPriority$1
flushSyncCallbackQueueImpl
flushSyncCallbackQueue
discreteUpdates$1
discreteUpdates
dispatchDiscreteEvent
bind_applyFunctionN self-hosted:1133
dispatchDiscreteEvent self-hosted:1096

This is the full page error I sometimes get:

TypeError: element.focus is not a function
onMouseDown
node_modules/reakit/es/Dialog/Dialog.js:65

62 | var onMouseDown = function onMouseDown(event) {
63 | var element = event.currentTarget;
64 | event.preventDefault();

65 | element.focus();
| ^ 66 | };
67 |
68 | var disclosure = ((_options$unstable_dis = options.unstable_disclosureRef) === null || _options$unstable_dis === void 0 ? void 0 : _options$unstable_dis.current) || ref.current;

EventListener.handleEvent*useDisclosureRef/<
node_modules/reakit/es/Dialog/Dialog.js:69

66 | };
67 |
68 | var disclosure = ((_options$unstable_dis = options.unstable_disclosureRef) === null || _options$unstable_dis === void 0 ? void 0 : _options$unstable_dis.current) || ref.current;

69 | disclosure === null || disclosure === void 0 ? void 0 : disclosure.addEventListener("mousedown", onMouseDown);
| ^ 70 | return function () {
71 | return disclosure === null || disclosure === void 0 ? void 0 : disclosure.removeEventListener("mousedown", onMouseDown);
72 | };

commitHookEffectListMount
node_modules/react-dom/cjs/react-dom.development.js:19731

19728 | if ((effect.tag & tag) === tag) {
19729 | // Mount
19730 | var create = effect.create;

19731 | effect.destroy = create();
| ^ 19732 |
19733 | {
19734 | var destroy = effect.destroy;

commitPassiveHookEffects
node_modules/react-dom/cjs/react-dom.development.js:19769

19766 | // before calling any create functions. The current approach only serializes
19767 | // these for a single fiber.
19768 | commitHookEffectListUnmount(Passive$1 | HasEffect, finishedWork);

19769 | commitHookEffectListMount(Passive$1 | HasEffect, finishedWork);
| ^ 19770 | break;
19771 | }
19772 | }

callCallback
node_modules/react-dom/cjs/react-dom.development.js:188

185 | window.event = windowEvent;
186 | }
187 |

188 | func.apply(context, funcArgs);
| ^ 189 | didError = false;
190 | } // Create a global error event handler. We use this to capture the value
191 | // that was thrown. It's possible that this error handler will fire more

invokeGuardedCallbackDev
node_modules/react-dom/cjs/react-dom.development.js:237

234 | // errors, it will trigger our global error handler.
235 |
236 | evt.initEvent(evtType, false, false);

237 | fakeNode.dispatchEvent(evt);
| ^ 238 |
239 | if (windowEventDescriptor) {
240 | Object.defineProperty(window, 'event', windowEventDescriptor);

invokeGuardedCallback
node_modules/react-dom/cjs/react-dom.development.js:292

289 | function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) {
290 | hasError = false;
291 | caughtError = null;

292 | invokeGuardedCallbackImpl$1.apply(reporter, arguments);
293 | }
294 | /**
295 | * Same as invokeGuardedCallback, but instead of returning an error, it stores

flushPassiveEffectsImpl
node_modules/react-dom/cjs/react-dom.development.js:22853

22850 | while (_effect2 !== null) {
22851 | {
22852 | setCurrentFiber(_effect2);

22853 | invokeGuardedCallback(null, commitPassiveHookEffects, null, _effect2);
| ^ 22854 |
22855 | if (hasCaughtError()) {
22856 | if (!(_effect2 !== null)) {

unstable_runWithPriority
node_modules/scheduler/cjs/scheduler.development.js:653

650 | currentPriorityLevel = priorityLevel;
651 |
652 | try {

653 | return eventHandler();
| ^ 654 | } finally {
655 | currentPriorityLevel = previousPriorityLevel;
656 | }

runWithPriority$1
node_modules/react-dom/cjs/react-dom.development.js:11039

11036 |
11037 | function runWithPriority$1(reactPriorityLevel, fn) {
11038 | var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);

11039 | return Scheduler_runWithPriority(priorityLevel, fn);
11040 | }
11041 | function scheduleCallback(reactPriorityLevel, callback, options) {
11042 | var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);

flushPassiveEffects
node_modules/react-dom/cjs/react-dom.development.js:22820

22817 | if (pendingPassiveEffectsRenderPriority !== NoPriority) {
22818 | var priorityLevel = pendingPassiveEffectsRenderPriority > NormalPriority ? NormalPriority : pendingPassiveEffectsRenderPriority;
22819 | pendingPassiveEffectsRenderPriority = NoPriority;

22820 | return runWithPriority$1(priorityLevel, flushPassiveEffectsImpl);
22821 | }
22822 | }
22823 |

performSyncWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js:21737

21734 | }
21735 | }
21736 |

21737 | flushPassiveEffects(); // If the root or expiration time have changed, throw out the existing stack
| ^ 21738 | // and prepare a fresh one. Otherwise we'll continue where we left off.
21739 |
21740 | if (root !== workInProgressRoot || expirationTime !== renderExpirationTime$1) {

flushSyncCallbackQueueImpl/<
node_modules/react-dom/cjs/react-dom.development.js:11089

11086 | var callback = queue[i];
11087 |
11088 | do {

11089 | callback = callback(_isSync);
| ^ 11090 | } while (callback !== null);
11091 | }
11092 | });

unstable_runWithPriority
node_modules/scheduler/cjs/scheduler.development.js:653

650 | currentPriorityLevel = priorityLevel;
651 |
652 | try {

653 | return eventHandler();
| ^ 654 | } finally {
655 | currentPriorityLevel = previousPriorityLevel;
656 | }

runWithPriority$1
node_modules/react-dom/cjs/react-dom.development.js:11039

11036 |
11037 | function runWithPriority$1(reactPriorityLevel, fn) {
11038 | var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);

11039 | return Scheduler_runWithPriority(priorityLevel, fn);
11040 | }
11041 | function scheduleCallback(reactPriorityLevel, callback, options) {
11042 | var priorityLevel = reactPriorityToSchedulerPriority(reactPriorityLevel);

flushSyncCallbackQueueImpl
node_modules/react-dom/cjs/react-dom.development.js:11084

11081 | try {
11082 | var _isSync = true;
11083 | var queue = syncQueue;

11084 | runWithPriority$1(ImmediatePriority, function () {
| ^ 11085 | for (; i < queue.length; i++) {
11086 | var callback = queue[i];
11087 |

flushSyncCallbackQueue
node_modules/react-dom/cjs/react-dom.development.js:11072

11069 | Scheduler_cancelCallback(node);
11070 | }
11071 |

11072 | flushSyncCallbackQueueImpl();
11073 | }
11074 |
11075 | function flushSyncCallbackQueueImpl() {

discreteUpdates$1
node_modules/react-dom/cjs/react-dom.development.js:21893

21890 |
21891 | if (executionContext === NoContext) {
21892 | // Flush the immediate callbacks that were scheduled during this batch

21893 | flushSyncCallbackQueue();
21894 | }
21895 | }
21896 | }

discreteUpdates
node_modules/react-dom/cjs/react-dom.development.js:806

803 | isInsideEventHandler = true;
804 |
805 | try {

806 | return discreteUpdatesImpl(fn, a, b, c, d);
| ^ 807 | } finally {
808 | isInsideEventHandler = prevIsInsideEventHandler;
809 |

dispatchDiscreteEvent
node_modules/react-dom/cjs/react-dom.development.js:4168

4165 |
4166 | function dispatchDiscreteEvent(topLevelType, eventSystemFlags, container, nativeEvent) {
4167 | flushDiscreteUpdatesIfNeeded(nativeEvent.timeStamp);

4168 | discreteUpdates(dispatchEvent, topLevelType, eventSystemFlags, container, nativeEvent);
4169 | }
4170 |
4171 | function dispatchUserBlockingUpdate(topLevelType, eventSystemFlags, container, nativeEvent) {

EventListener.handleEvent*addEventCaptureListener
node_modules/react-dom/cjs/react-dom.development.js:4030

4027 | element.addEventListener(eventType, listener, false);
4028 | }
4029 | function addEventCaptureListener(element, eventType, listener) {

4030 | element.addEventListener(eventType, listener, true);
4031 | }
4032 |
4033 | // do it in two places, which duplicates logic

trapEventForPluginEventSystem
node_modules/react-dom/cjs/react-dom.development.js:4160

4157 | var rawEventName = getRawEventName(topLevelType);
4158 |
4159 | if (capture) {

4160 | addEventCaptureListener(container, rawEventName, listener);
| ^ 4161 | } else {
4162 | addEventBubbleListener(container, rawEventName, listener);
4163 | }

trapCapturedEvent
node_modules/react-dom/cjs/react-dom.development.js:4136

4133 | trapEventForPluginEventSystem(element, topLevelType, false);
4134 | }
4135 | function trapCapturedEvent(topLevelType, element) {

4136 | trapEventForPluginEventSystem(element, topLevelType, true);
4137 | }
4138 |
4139 | function trapEventForPluginEventSystem(container, topLevelType, capture) {

legacyListenToTopLevelEvent
node_modules/react-dom/cjs/react-dom.development.js:3613

3610 |
3611 | case TOP_FOCUS:
3612 | case TOP_BLUR:

3613 | trapCapturedEvent(TOP_FOCUS, mountAt);
| ^ 3614 | trapCapturedEvent(TOP_BLUR, mountAt); // We set the flag for a single dependency later in this function,
3615 | // but this ensures we mark both as attached rather than just one.
3616 |

legacyListenToEvent
node_modules/react-dom/cjs/react-dom.development.js:3601

3598 |
3599 | for (var i = 0; i < dependencies.length; i++) {
3600 | var dependency = dependencies[i];

3601 | legacyListenToTopLevelEvent(dependency, mountAt, listenerMap);
3602 | }
3603 | }
3604 | function legacyListenToTopLevelEvent(topLevelType, mountAt, listenerMap) {

ensureListeningTo
node_modules/react-dom/cjs/react-dom.development.js:5761

5758 | function ensureListeningTo(rootContainerElement, registrationName) {
5759 | var isDocumentOrFragment = rootContainerElement.nodeType === DOCUMENT_NODE || rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
5760 | var doc = isDocumentOrFragment ? rootContainerElement : rootContainerElement.ownerDocument;

5761 | legacyListenToEvent(registrationName, doc);
5762 | }
5763 |
5764 | function getOwnerDocumentFromRootContainer(rootContainerElement) {

setInitialProperties
node_modules/react-dom/cjs/react-dom.development.js:5995

5992 | trapBubbledEvent(TOP_INVALID, domElement); // For controlled components we always need to ensure we're listening
5993 | // to onChange. Even if there is no listener.
5994 |

5995 | ensureListeningTo(rootContainerElement, 'onChange');
| ^ 5996 | break;
5997 |
5998 | case 'option':

finalizeInitialChildren
node_modules/react-dom/cjs/react-dom.development.js:7499

7496 | parentInstance.appendChild(child);
7497 | }
7498 | function finalizeInitialChildren(domElement, type, props, rootContainerInstance, hostContext) {

7499 | setInitialProperties(domElement, type, props, rootContainerInstance);
7500 | return shouldAutoFocusHostComponent(type, props);
7501 | }
7502 | function prepareUpdate(domElement, type, oldProps, newProps, rootContainerInstance, hostContext) {

completeWork
node_modules/react-dom/cjs/react-dom.development.js:18978

18975 | // Make sure such renderers get scheduled for later work.
18976 |
18977 |

18978 | if (finalizeInitialChildren(instance, type, newProps, rootContainerInstance)) {
| ^ 18979 | markUpdate(workInProgress);
18980 | }
18981 | }

completeUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:22192

22189 | next = completeWork(current, workInProgress, renderExpirationTime$1);
22190 | } else {
22191 | startProfilerTimer(workInProgress);

22192 | next = completeWork(current, workInProgress, renderExpirationTime$1); // Update render duration assuming we didn't error.
| ^ 22193 |
22194 | stopProfilerTimerIfRunningAndRecordDelta(workInProgress, false);
22195 | }

performUnitOfWork
node_modules/react-dom/cjs/react-dom.development.js:22165

22162 |
22163 | if (next === null) {
22164 | // If this doesn't spawn new work, complete the current work.

22165 | next = completeUnitOfWork(unitOfWork);
| ^ 22166 | }
22167 |
22168 | ReactCurrentOwner$2.current = null;

workLoopSync
node_modules/react-dom/cjs/react-dom.development.js:22130

22127 | function workLoopSync() {
22128 | // Already timed out, so perform work without checking if we need to yield.
22129 | while (workInProgress !== null) {

22130 | workInProgress = performUnitOfWork(workInProgress);
22131 | }
22132 | }
22133 | /** @noinline */

performSyncWorkOnRoot
node_modules/react-dom/cjs/react-dom.development.js:21756

21753 |
21754 | do {
21755 | try {

21756 | workLoopSync();
| ^ 21757 | break;
21758 | } catch (thrownValue) {
21759 | handleError(root, thrownValue);

scheduleUpdateOnFiber
node_modules/react-dom/cjs/react-dom.development.js:21188

21185 | // root inside of batchedUpdates should be synchronous, but layout updates
21186 | // should be deferred until the end of the batch.
21187 |

21188 | performSyncWorkOnRoot(root);
| ^ 21189 | } else {
21190 | ensureRootIsScheduled(root);
21191 | schedulePendingInteractions(root, expirationTime);

updateContainer
node_modules/react-dom/cjs/react-dom.development.js:24373

24370 | }
24371 |
24372 | enqueueUpdate(current$1, update);

24373 | scheduleWork(current$1, expirationTime);
24374 | return expirationTime;
24375 | }
24376 | function getPublicRootInstance(container) {

legacyRenderSubtreeIntoContainer/<
node_modules/react-dom/cjs/react-dom.development.js:24758

24755 |
24756 |
24757 | unbatchedUpdates(function () {

24758 | updateContainer(children, fiberRoot, parentComponent, callback);
| ^ 24759 | });
24760 | } else {
24761 | fiberRoot = root._internalRoot;

unbatchedUpdates
node_modules/react-dom/cjs/react-dom.development.js:21903

21900 | executionContext |= LegacyUnbatchedContext;
21901 |
21902 | try {

21903 | return fn(a);
| ^ 21904 | } finally {
21905 | executionContext = prevExecutionContext;
21906 |

legacyRenderSubtreeIntoContainer
node_modules/react-dom/cjs/react-dom.development.js:24757

24754 | } // Initial mount should not be batched.
24755 |
24756 |

24757 | unbatchedUpdates(function () {
| ^ 24758 | updateContainer(children, fiberRoot, parentComponent, callback);
24759 | });
24760 | } else {

render
node_modules/react-dom/cjs/react-dom.development.js:24840

24837 | }
24838 | }
24839 |

24840 | return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
24841 | }
24842 | function unstable_renderSubtreeIntoContainer(parentComponent, element, containerNode, callback) {
24843 | if (!isValidContainer(containerNode)) {

./src/index.js
src/index.js:8

5 |
6 | import App from "./App";
7 |

8 | ReactDOM.render(
9 | <React.StrictMode>
10 |
11 |

webpack_require
/Users/wwb/Projekte/Ignore/bumbag/webpack/bootstrap:784

781 | };
782 |
783 | // Execute the module function

784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;

fn
/Users/wwb/Projekte/Ignore/bumbag/webpack/bootstrap:150

147 | );
148 | hotCurrentParents = [];
149 | }

150 | return webpack_require(request);
| ^ 151 | };
152 | var ObjectFactory = function ObjectFactory(name) {
153 | return {

1
http://localhost:3000/static/js/main.chunk.js:271:18
webpack_require
/Users/wwb/Projekte/Ignore/bumbag/webpack/bootstrap:784

781 | };
782 |
783 | // Execute the module function

784 | modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
| ^ 785 |
786 | // Flag the module as loaded
787 | module.l = true;

checkDeferredModules
/Users/wwb/Projekte/Ignore/bumbag/webpack/bootstrap:45

42 | }
43 | if(fulfilled) {
44 | deferredModules.splice(i--, 1);

45 | result = webpack_require(webpack_require.s = deferredModule[0]);
| ^ 46 | }
47 | }
48 |

webpackJsonpCallback
/Users/wwb/Projekte/Ignore/bumbag/webpack/bootstrap:32

29 | deferredModules.push.apply(deferredModules, executeModules || []);
30 |
31 | // run deferred modules when all chunks ready

32 | return checkDeferredModules();
| ^ 33 | };
34 | function checkDeferredModules() {
35 | var result;

(anonymous function)
http://localhost:3000/static/js/main.chunk.js:1:75

Tables Overflow

When a table has more columns than the container width just cuts.

To Reproduce

  1. Create a table with many columns

Expected behavior

Some scrollbar or toggle collapse

Screenshots
image

Device information (please complete the following information):

  • Device: PC
  • OS, version: Windows 10 Home
  • Browser, version: Chrome, 86.0.4240.75

Additional context

Tried with style={{overFlowX: "auto"}} with no success

Thanks!

Keyboard navigation issues on the website

Problem

The main content area in the /components section is difficult to access using the keyboard.

How to Reproduce

Open https://bumbag.style/components/button/, click area around the buttons in the first example, then hit tab.

Current Behavior

The "TopNavItem" (Bumbag logo/link) on the top left takes the focus. To make matters worse, I have to tab through all the options in the top menu and all the links on the left nav in order to get to the main content.

Expected Behavior

Either or both one of these:

Customize spacing of ActionButtons

Is your feature request related to a problem? Please describe.

When adding ActionButtons to a Dialog, I want to add a space-between the two buttons so the cancel button will be placed on the left of the footer and the primary button be placed on the right side of the footer.
Example:
example.png

Describe the solution you'd like

We should implement an API to be able to add space, space-out the two buttons.

Describe alternatives you've considered

I've tried using the normal Button components and the footer prop on Dialog.Modal but I had the same issue as #54

Playroom: link

Writing mode & RTL layout issues

Describe the bug

When adding direction="rtl" to the page some components layout looks broken.
And other components have prop values of left and right but when the direction changes the values aren't semantically correct.

To Reproduce

Playroom examples with broken layout when the direction is rtl:
Alert: Link
Group: Link
Blockquote: link
Code Block: link (I think this could have a fixed direction of ltr since code is written in ltr)
List: link
Badge: link (should be attached to the top-left)
Breadcrumb: link
Button with Icon: link
Callout: link (close icon should be on the left)
Card > Header with addons: link (the header and footer action buttons have a fixed margin-left)
Dialog: link
DropdownMenu: link
Menu: link
Pagination: link
Popover: link (ActionButtons have fixed margin-left)
Rating: link (accessibility: keyboard navigation is going in the opposite direction)
SideNav: link
Table: link (table has a default text-align with value left, would be better to have the value to be start)
Tabs: Link
Tag: link
Toast: link
TopNav: link (TopNav.Item last child has a fixed margin-right)
Autosuggest: link
Checkbox: link
CheckboxGroup: link (checkbox items have a fixed margin-left)
FieldStack: link
FieldWrapper: link
Radio: link
RadioGroup: link
Select: link
SelectMenu: link (the tags have a fixed margin-left)
Switch: link
Rover: link (accessibility: keyboard navigation is going in the opposite direction)

Components with prop values that aren't semantic with the writing direction:
Container (align): link
Set (alignX): link
Stack (alignX): link
Tabs.List (align): link
ToastManager (placement)?: link (couldn't find docs on the API of ToastManager)
Tooltip (placement, arrowProps.expand): link
Drawer (placement): link
Modal (placement): link
Overlay (placement): link

Expected behavior

For the components to use a writing mode agnostic CSS properties such as CSS Logical Properties and Values(margin-inline-start, padding-inline-end, etc.) and have prop values that respect the writing mode, ex. rather than left and right we could use start and end values.

I know that this will require changes across a lot of components so I am willing to help out ๐Ÿ˜„.

Can't specify width of Dialog footer

Describe the bug

When passing a component with the prop width="100%" to Dialog.Modal's footer prop, the footer still takes the width of the content of the passed component.

To Reproduce

  1. pass <Box width="100%" backgroundColor="primary">hello</Box> to Dialog.Modal's footer prop

Expected behavior

The passed component should take the full width of the footer

Screenshots

Playroom: link

Device information (please complete the following information):

  • Device: Desktop
  • OS, version: Windows 10
  • Browser, version: Chrome v84.0.4147.135

Textarea - make size adjustable

Please consider providing more flexibility to control the size of a Textarea component. Right now, sizes are provided, but setting size= small, medium or large affects both the height of the text area and the font size. I'd like to be able to specify the font size and the number of rows visible independently. This could be as simple as exposing the HTML "rows=". It would also be nice to be able to set the textarea so that it is not resizable by the user (get rid of handle in lower right), but still allows scrolling.

Pagination not using the available space when having wide columns

Describe the bug

As soon as the content of a Table.Cell gets wider than 11 characters, the Pagination in the footer will collapse and display a mobile version where the last elements are pushed into a new line for every resolution bigger than 375px.

To Reproduce

See this Playroom example

Change the text of the last column to be shorter or longer and see the result.

Expected behavior
The Pagination element would use the full width and only push the last elements to a new line if the space is not enough. This is correct for any resolution below 375px.

Screenshots
Actual:

image

Expected:
image

Configure SelectMenu with Typescript

Hi guys.
How can I configure the props onChange() and value element SelectMenu to works with Typescript.

I try this many ways, but is not working...

const [fruits, setFruits] = useState();
....
             <SelectMenu
                  hasTags
                  isMultiSelect
                  onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
                    setFruits(e.target.value);
                  }}
                  options={[
                    { key: 1, label: 'Apples', value: 'apples' },
                    { key: 2, label: 'Bananas', value: 'bananas' },
                    { key: 3, label: 'Oranges', value: 'oranges' },
                    { key: 4, label: 'Mangos', value: 'mangos' },
                  ]}
                  placeholder="Select a fruit..."
                  value={fruits}
               />

Error:

TypeScript error in /mnt/c/Users/kados/Documents/Dev/projetos/harpa-crista/admin/src/pages/Hinos/Editar/index.tsx(127,19):
Type '(e: React.ChangeEvent<HTMLSelectElement>) => void' is not assignable to type '((event: FormEvent<any>) => void) & ((newOptions: "" | Option | Option[], option: "" | Option) => void)'.
  Type '(e: React.ChangeEvent<HTMLSelectElement>) => void' is not assignable to type '(newOptions: "" | Option | Option[], option: "" | Option) => void'.
    Types of parameters 'e' and 'newOptions' are incompatible.
      Type '"" | Option | Option[]' is not assignable to type 'ChangeEvent<HTMLSelectElement>'.
        Type '""' is not assignable to type 'ChangeEvent<HTMLSelectElement>'.  TS2322

    125 |                   hasTags
    126 |                   isMultiSelect
  > 127 |                   onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
        |                   ^
    128 |                     setFruits(e.target.value);
    129 |                   }}
    130 |                   options={[

[ask] Add navId to Menu.Item

Is your feature request related to a problem? Please describe.

I don't know how to manage active menu item properly.

Doing it like in Top.Nav using navId="id" would be useful.

as you can see it works great with next/router pathnames for active. I might need to refactor for not so simple routes like 1st level ones only but still!

See as mobile in dev-tools to see drawer-mode menu
https://webapp.agu.vercel.app/

my current code

import { TopNav, Image, Hide, Button, Drawer, Menu } from 'bumbag';
import Link from 'next/link';
import { useRouter } from 'next/router'
import React from 'react'
function Header() {
    const router = useRouter()
    console.log(router.pathname)
    //@ts-ignore
      const [selectedId, setSelectedId] = React.useState( router.pathname )
      return(
        <>
<Hide below="desktop">
{/*
 // @ts-ignore*/}
        <TopNav selectedId={selectedId} onChange={(id:{id: any})=> setSelectedId(id)}>
      <TopNav.Section>
        <Link href="/">
        <TopNav.Item navId="/" >
          <Image src="/logo.svg" maxWidth="130px"  style={{cursor: 'pointer', paddingLeft: 20}} />
        </TopNav.Item>
                    </Link>
          <Link href="/cruises">
        <TopNav.Item navId="/cruises" >
            Cruceros
        </TopNav.Item>
          </Link>
          <Link href="/luxury">
        <TopNav.Item navId="/luxury">
            Lujo
        </TopNav.Item>
          </Link>
          <Link href="/river">
        <TopNav.Item navId="/river">
            Fluviales
        </TopNav.Item>
          </Link>
      </TopNav.Section>
      <TopNav.Section marginRight="major-5">
          <Link href="/signup">
        <TopNav.Item navId="/signup">
            {/* <Button variant="ghost"  size='small' palette="primary"> */}
            Registro
            {/* </Button> */}
        </TopNav.Item>
          </Link>
            <Link href="/login">
        <TopNav.Item navId="/login">
                {/* <Button variant="call-to-action" size="small" palette="primary"> */}

                Entrar
                {/* </Button> */}
        </TopNav.Item>
            </Link>
      </TopNav.Section>
    </TopNav>
</Hide>
<Hide above="desktop">
    <TopNav>
      <TopNav.Section  marginLeft="major-1" >
          <TopNav.Item>
            <Drawer.State>
              <Drawer.Disclosure>
                <Button iconBefore="solid-bars">
                MENU
                </Button>
              </Drawer.Disclosure>
           <Drawer>
        <Menu>
      <Menu.Group >
        <Link href="/">
        <Menu.Item >
          <Image src="/logo.svg" maxWidth="240px"  style={{cursor: 'pointer'}} />
        </Menu.Item>
                    </Link>
        </Menu.Group>
              <Menu.Group title="Cruceros">

          <Link href="/cruises">
        <Menu.Item  >
            Cruceros
        </Menu.Item>
          </Link>
          <Link href="/luxury">
        <Menu.Item >
            Lujo
        </Menu.Item>
          </Link>
          <Link href="/river">
        <Menu.Item >
            Fluviales
        </Menu.Item>
          </Link>
      </Menu.Group>
        <Menu.Divider />
      <Menu.Group title="Area de cliente">
          <Link href="/signup">
        <Menu.Item >
            {/* <Button variant="ghost"  size='small' palette="primary"> */}
            Registro
            {/* </Button> */}
        </Menu.Item>
          </Link>
            <Link href="/login">
        <Menu.Item >
                {/* <Button variant="call-to-action" size="small" palette="primary"> */}

                Entrar
                {/* </Button> */}
        </Menu.Item>
            </Link>
      </Menu.Group>
    </Menu>
  </Drawer>
</Drawer.State>
    </TopNav.Item>
      {/* </TopNav.Section> */}
            {/* <TopNav.Section> */}
          <TopNav.Item>
          <Image src="/logo.svg" maxWidth="130px"  style={{cursor: 'pointer', paddingLeft: 10}} />
          </TopNav.Item>
      </TopNav.Section>
    </TopNav>
</Hide>
</>
    )
}

export default Header

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.