Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propose a new file structure (ADR) #1678

Merged
merged 8 commits into from
Dec 16, 2021
Merged

Conversation

jfuchs
Copy link
Contributor

@jfuchs jfuchs commented Dec 1, 2021

This PR adds a proposed ADR establishing a file convention.

There are two reasons I'm doing this:

  • I think the result would be good (more to come on that in the ADR)
  • I'm interested in seeing if we can keep ADRs fast and light for smaller questions

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.

@jfuchs jfuchs added the skip changeset This change does not need a changelog label Dec 1, 2021
@changeset-bot
Copy link

changeset-bot bot commented Dec 1, 2021

⚠️ No Changeset found

Latest commit: f252635

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Dec 1, 2021

size-limit report 📦

Path Size
dist/browser.esm.js 57.5 KB (0%)
dist/browser.umd.js 57.8 KB (0%)

@colebemis
Copy link
Contributor

Having a consistent file structure would also lay the groundwork for us to create a npm run new:component script to scaffold a new component 😄

Questions I would like to settle in this ADR:

- On subcomponents:
- Do subcomponents filenames need to be namespaced with the parent component? (e.g., `BreadCrumbsItem.tsx` vs `Item.tsx`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

➕ : Makes searching for related files easier in the IDE

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have to say first - super happy to go with what the majority of the team prefers. very loosely help opinions.

Aw, I was going to vote ➖ on this because it is scoped inside the component folder: src/Breadcrumb/Item.tsx.

For example, in VS Code, i would search for "action item" to look for ActionList/Item

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I prefer the longer more descriptive name.


- On subcomponents:
- Do subcomponents filenames need to be namespaced with the parent component? (e.g., `BreadCrumbsItem.tsx` vs `Item.tsx`)
- Should the `index.ts` in each component directory export every subcomponent under its own name, or should we prefer `Object.assign`ing subcomponents to the parent component?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it depend on whether the subcomponent is private to its parent and not intended for composition? I.e. With a compound component, I'd expect it the parent component to be the only one exported from the folder. Might be misunderstanding this point though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've seen two different styles:

  1. BreadCrumbsItem, which isn't exported on their own and is only accessed as BreadCrumbs.Item
  2. ButtonDanger, which is available as its own export.
    it is reasonable to me that those are different, as BreadCrumbsItem only makes sense as a child of BreadCrumbs.... and maybe we could name that as a rule? Alternately, we could consolidate to one style, right?

- Do subcomponents filenames need to be namespaced with the parent component? (e.g., `BreadCrumbsItem.tsx` vs `Item.tsx`)
- Should the `index.ts` in each component directory export every subcomponent under its own name, or should we prefer `Object.assign`ing subcomponents to the parent component?
- Should subcomponents always have their own test files? What about type tests and stories?
- Would this structure help if we wanted to move toward one-package-per-component like react-aria does?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach totally opens doors to this and makes codesplitting much easier to maintain. Big ➕

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense — personally I don't know enough about what makes tree shaking possible or not possible to be confident that separate packages are actually necessary.

@rezrah
Copy link
Contributor

rezrah commented Dec 2, 2021

Pretty hyped for this. It'll improve the experience across the board, for both contributors and consumers. Thanks for proposing it @jfuchs.

@colebemis colebemis added the react label Dec 6, 2021
- Should the `index.ts` in each component directory export every subcomponent under its own name, or should we prefer `Object.assign`ing subcomponents to the parent component?
- Should subcomponents always have their own test files? What about type tests and stories?
- Would this structure help if we wanted to move toward one-package-per-component like react-aria does?
- Could we set a standard for replacement components? E.g., NewButton vs. Button2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my personal vote is for src/drafts/Button or even src/drafts/Button2.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh interesting — can you say more about why you like that?

I hesitate because it'd mean advancing the status of a component from propsed -> alpha would have to be a breaking change, right?

Copy link
Member

@siddharthkp siddharthkp Dec 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hesitate because it'd mean advancing the status of a component from proposed -> alpha would have to be a breaking change, right?

Don't think so. we should use drafts for replacement components which can be at a more advanced maturity than their current counterpart. For example, ActionList v1 is alpha but ActionList v2 can be at beta maturity while being in drafts. This is why we chose drafts over other names. More context here: #1609 (comment)

I like it more because it matches the bundle scope. drafts are not part of the main index.js bundle.

Copy link
Member

@siddharthkp siddharthkp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it! ship it! :shipit:

- On subcomponents:
- Do subcomponents filenames need to be namespaced with the parent component? (e.g., `BreadCrumbsItem.tsx` vs `Item.tsx`)
- Should the `index.ts` in each component directory export every subcomponent under its own name, or should we prefer `Object.assign`ing subcomponents to the parent component?
- Should subcomponents always have their own test files? What about type tests and stories?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. There are going to be subcomponents that rely on some context to get passed down from the parent.

@pksjce pksjce marked this pull request as ready for review December 9, 2021 06:48
@pksjce pksjce requested review from a team and mperrotti December 9, 2021 06:48
@pksjce pksjce marked this pull request as draft December 9, 2021 06:48

- Every component should have its own PascalCased directory directly under `src/`
- Subcomponents meant to be used as children of their parent component should be properties of the exported component (e.g., `BreadCrumbs.Item`)
- Subcomponents meant to be used on their own should be exported as a named export (e.g., `ButtonDanger`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a pattern we want to encourage?

I'd argue that it's not a "subcomponent" if it's exported on its own. If it's not a property of a parent component, I think it should probably have it's own directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like simple rules.... but thinking about that with ButtonDanger.... that doesn't feel like it merits its own component, and I'm not sure I'd want that to just be a prop on Button (i.e., <Button variant="danger"...). Would you say ButtonDanger should have its own directory?

Copy link
Contributor

@colebemis colebemis Dec 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'd want that to just be a prop on Button (i.e., <Button variant="danger"...)

FYI ButtonDanger is going away in favor of a variant prop. @pksjce's Button2 uses that API.

I don't think we plan to have any components like ButtonDanger in the future

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay cool. That settles it then :-)

### Rules

- Every component should have its own PascalCased directory directly under `src/`
- Subcomponents meant to be used as children of their parent component should be properties of the exported component (e.g., `BreadCrumbs.Item`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean that the Object.assign happens in Breadcrumbs.tsx or index.tsx?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't mean to specify — but if you think this should I'm fine with that!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add more rules to this doc as we form opinions. So I guess it's fine to be vague now.

IMO, the Object.assign should happen in Breadcrumbs.tsx. index.tsx seems mostly like an implementation detail to make imports nicer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should index.tsx export default or named?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I lean towards named export. In general, I'm not a big fan of default exports (unless they're necessary for some reason)

@jfuchs jfuchs merged commit b05472e into main Dec 16, 2021
@jfuchs jfuchs deleted the jfuchs/structure-conventions branch December 16, 2021 23:20
pksjce pushed a commit that referenced this pull request Dec 20, 2021
* Proposes a new file structure (ADR)

* Update contributor-docs/adrs/adr-XXX-file-structure.md

Co-authored-by: Cole Bemis <colebemis@github.com>

* More questions about the implementation process

* Doc updates; removal of open questions

* BreadCrumbs -> Breadcrumbs

* Remove note about separately exported subcomponents

* Update contributor-docs/adrs/adr-XXX-file-structure.md

Co-authored-by: Cole Bemis <colebemis@github.com>

Co-authored-by: Cole Bemis <colebemis@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
react skip changeset This change does not need a changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants