Migrating Components (from ACL UI) - acl-services/paprika GitHub Wiki
- Create a new sub folder in packages for your new component.
- Copy the file/folder structure of an existing component (a simple example is the
<RawButton>
). - Use
PascalCase
for your component file and its associated styles.js file (egHeading.js
/Heading.styles.js
). - Include a package.json (again an existing component can be used as a base, but be sure to update
name
,description
, andrepository.url
) - The
version
for a typical new component should bev0.1.0
.
- Booleans should be prefixed with:
is
(or sometimesare
),has
.can
, orshould
. - Event handlers that perform an action in a component should be prefixed with
handle
and followed by the event and finally the object. (eghandleClickButton
). - An event handler that is passed as a prop is distinguished by an
on
prefix (egonPressEsc
). -
size
is typically handled with a custom PropType,shirtSize
(see<Button>
as an example). -
ariaText
orariaLabel
should typically be replaced witha11yText
.
- Declare
const propTypes
andconst defaultProps
at the top of the file and attach them to the component at the bottom (egMyComponent.propTypes = propTypes;
). - Include
MyComponent.displayName = "My Component";
- The root node for the component likely won't need an identifying
className
anymore withstyled-components
, but instead can include an attribute to identify it (egdata-pka-anchor="my-component"
). - Internal elements that also need a CSS handle, can use the same
data-pka-anchor
attribute – use a.
as a delimiter (egdata-pka-anchor="my-component.some-element"
). - If an internal
ref
is only needed for focus management, it is preferred to useuseImperativeHandle
to expose afocus()
method instead (see<Button>
as an example).
- Styles are declared and exported in a
styles.js
file. - Define styling in template literals, but use the
styled-components
css
helper function to improve the DX in code editors and help with static analysis tools (egconst myStyles = css`.my-selector { ... }`;
). - Import the
myStyles
into yourjsx
and apply to your root element with thecss
prop (eg<MyComponent css={myStyles} />
) - Since the styles are applied directly, there is no need for a root class name (like
aclui-button
), but rather than refactor all descendent elements, it is preferred forv0.1.0
to simply maintain class names (likeaclui-button--content
) so the CSS can simply be copied over intact. - Class names that do remain should have the
aclui-
prefix removed. - Most Sass features are supported in
styled-components
, but some exceptions are@mixins
+@includes
(helpful ones have been converted to JS functions in thestylers
package). - One exception is the use of the
&
in the middle or end of a selector (eg.is-disabled & { ... };
) which will need to be refactored. - Tokens and helper functions can be included with:
import tokens from "@paprika/tokens"; import stylers from "@paprika/stylers";
- For tokens, the JS version will be needed instead of the Sass version. Name in general can be converted by switching to
camelCase
fromkebab-case
, and replacing--
with.
(eg$color--black-lighten-10
→${tokens.color.blackLighten10}
). - For a spacing:
-
$space
→${tokens.space}
-
$space-sm
→${tokens.spaceSm}
-
$space-lg
→${tokens.spaceLg}
-
$space * 2
→${stylers.spacer(2)}
-
- Some other helpful
stylers
includefontSize()
,lineHeight()
,zIndex()
. - Component props can be accessed and used to apply styling conditionally, but it is preferred to destructure the
props
first (egcolor: ${({isDisabled}) => isDisabled ? 'red' : null}
). - See
Button.styles.js
for many more examples, as well as the Storybook story forStylers
).
- Stories are kept in the component package, in the
stories
folder, with astories.js
suffix that allows them to be added to the Storybook automatically. - The Design System team will be responsible for curating the Storybook. As a casual contributor, there are no other particular conventions to follow.
- You are encouraged to add as many stories as you need and be as creative as you like, but your stories will eventually end up filed away in a
dev
folder in the Storybook UI. - If there are Storybook stories in
acl-ui
, it makes sense to migrate them as well.
- There are three levels of test coverage that can currently be applied to components in Paprika: Screener, React Testing Library, and Cypress.
- Visual regressions can be covered first in a basic Screener story in Storybook that includes all options. If the component is not interactive, this may suffice for test coverage.
- For basic interactions, React Testing Library can run much faster, and is generally preferred (add to the package as
tests/MyComponent.spec.js
). - For more complicated interactions or where RTL is not reliable enough, Cypress can be employed (another Storybook story will be needed in this case).
- The
<Popover>
is a good example component as it has all three types of test.