-
-
Notifications
You must be signed in to change notification settings - Fork 125
Recipes
Cookin' Up Tasty Features
Take a look at the pages/bills.tsx
page:
export default createPage({
title: "Browse",
Page: () => {
return (
<Container>
<h1>Browse</h1>
...
</Container>
);
},
});
Your page content goes in Page
, and will be wrapped in a layout component. The page is rendered by _app.tsx
.
Suppose you're adding a BillWidget
to the bill detail page. Add your component to the components/bill
folder:
// components/bill/BillWidget.tsx
import { FC } from "react";
import styled from "styled-components";
export const StyledWidget = styled.div`
border-radius: 1rem;
background: white;
padding: 0.5rem 1rem 1rem 0.5rem;
border: 1px solid var(--bs-red);
`;
export const BillWidget: FC<{ billId?: string }> = ({ billId }) => (
<StyledWidget>
{billId ? `This is bill ${billId}` : "No bill selected"}
</StyledWidget>
);
Then create a story for it in stories/billDetail
:
// stories/billDetail/BillWidget.stories.tsx
import { ComponentStory } from "@storybook/react";
import { BillWidget } from "components/bill/BillWidget";
import { createMeta } from "stories/utils";
export default createMeta({
title: "Bill Detail/BillWidget",
component: BillWidget,
});
const Template: ComponentStory<typeof BillWidget> = (args) => (
<BillWidget {...args} />
);
export const WithBillId = Template.bind({});
WithBillId.args = { billId: "H1234" };
export const WithoutBillId = Template.bind({});
WithoutBillId.args = {};
All components should live in the components
directory and be grouped by feature. For example, components related to the bill detail page live under components/bill
, and auth modals live under auth
. There are many components that do not follow this pattern, but the goal is to consolidate around this in the future. For example there are several About*
component folders that could be grouped under an about
feature folder.
Files that export a single component should be named in title case after that component, like bill/BillDetails.tsx
. The component should be exported as a named export, not a default export, for better intellisense:
// bill/BillDetails.tsx
export const BillDetails = ({ billId }: { billId: string }) => { ... }
Other files should be named using camelCase
. For example, bills/types.ts
exports types shared across components. Files that export a mix of components and support functions like hooks should be named with camelCase
, such as legislatorSearch.tsx
, which exports both UI components and hooks.
Within a folder, modules can import other modules directly, such as import { ChooseStance } from "./ChooseStance"
from publish/SubmitTestimonyForm.tsx
. To import something between feature folders, use an index.ts
file to re-export modules for easier importing:
// bill/index.ts
export * from "./BillDetails"
// pages/bill.tsx
import { BillDetails } from "../components/bill"
...
When in doubt, do whatever makes sense to you. Contributions are more important than conventions.
We heavily use react-bootstrap
components and bootstrap v5
utility classes for spacing and CSS variables for color.
We have a small amount of global CSS for customizing our Bootstrap theme and external libraries.
All other styling should use either CSS modules or Styled Components. You can use style props directly for dynamically changing styling.
- CSS Modules
- Styled Components
- Style props
You should create stories for your components to make it easy to see the UI in different states. All stories should go under the stories
directory. See stories/components/cards/Card.stories.tsx
for an example story.