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

Migrate components to CSS Modules #2163

Merged
merged 68 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
ea0dd73
Recommend VS Code extensions
connor-baer Jun 16, 2023
8917a56
Don't lint generated theme
connor-baer Jun 25, 2023
39265fa
Lint CSS in CI
connor-baer Jun 25, 2023
d9072d1
Build with Vite for CSS module support
connor-baer May 4, 2023
6d31aa2
Use relative imports in Storybook components
connor-baer May 4, 2023
ba58068
Support CSS custom properties in style attribute
connor-baer May 4, 2023
1ee2c21
Add clsx util for classnames
connor-baer May 4, 2023
88950ba
Add utility classes
connor-baer May 5, 2023
52cc2f6
Migrate Hr component to CSS modules
connor-baer May 4, 2023
ee95406
Migrate Card component to CSS modules
connor-baer May 4, 2023
4fd4dfc
Migrate Button component to CSS modules
connor-baer May 26, 2023
0a18c09
Migrate IconButton component to CSS modules
connor-baer Jun 25, 2023
b249b4e
Migrate CloseButton component to CSS modules
connor-baer Jun 25, 2023
976b9ce
Migrate Spinner component to CSS modules
connor-baer Jun 25, 2023
6d84a8a
Migrate Headline component to CSS modules
connor-baer Jun 25, 2023
28a4b50
Migrate SubHeadline component to CSS modules
connor-baer Jun 25, 2023
b3af2c2
Migrate Body component to CSS modules
connor-baer Jun 25, 2023
b9642f0
Migrate BodyLarge component to CSS modules
connor-baer Jun 25, 2023
2289ec3
Migrate Anchor component to CSS modules
connor-baer Jun 25, 2023
616daf7
Migrate Title component to CSS modules
connor-baer Jun 25, 2023
5e421b2
Migrate List component to CSS modules
connor-baer Jun 25, 2023
51bb82f
Migrate AspectRatio component to CSS modules
connor-baer Jun 25, 2023
396cd7c
Migrate Avatar component to CSS modules
connor-baer Jun 26, 2023
71d0c31
Migrate Badge component to CSS modules
connor-baer Jun 26, 2023
aa578f0
Migrate Field atoms to CSS modules
connor-baer Jun 26, 2023
b93223a
Migrate Input components to CSS modules
connor-baer Jun 26, 2023
5960689
Migrate Select component to CSS modules
connor-baer Jun 26, 2023
3117baa
Migrate Pagination components to CSS modules
connor-baer Jun 27, 2023
7d53187
Migrate ProgressBar component to CSS modules
connor-baer Jun 27, 2023
8fa83e0
Migrate Hamburger component to CSS modules
connor-baer Jun 27, 2023
d84906f
Migrate Header component to CSS modules
connor-baer Jun 27, 2023
a4437d3
Migrate ImageInput component to CSS modules
connor-baer Jun 27, 2023
ba940f0
Migrate Image component to CSS modules
connor-baer Jun 28, 2023
4deab4e
Migrate Skeleton components to CSS modules
connor-baer Jun 28, 2023
f7442d5
Migrate Toggle component to CSS modules
connor-baer Jun 28, 2023
f49589d
Migrate Tag component to CSS modules
connor-baer Jun 28, 2023
1ae7be6
Migrate Checkbox components to CSS modules
connor-baer Jun 28, 2023
e07cb10
Migrate RadioButton components to CSS modules
connor-baer Jun 28, 2023
1f3ba99
Migrate Selector components to CSS modules
connor-baer Jun 28, 2023
94bbb02
Migrate Modal component to CSS modules
connor-baer Jun 28, 2023
cf08920
Migrate NotificationModal component to CSS modules
connor-baer Jun 28, 2023
6301600
Migrate NotificationBanner component to CSS modules
connor-baer Jun 28, 2023
152d2fa
Migrate NotificationFullscreen component to CSS modules
connor-baer Jun 28, 2023
a72ba78
Migrate NotificationInline component to CSS modules
connor-baer Jun 28, 2023
9f6b194
Migrate NotificationToast component to CSS modules
connor-baer Jun 28, 2023
a969a2a
Migrate style mixins to custom properties
connor-baer Jun 28, 2023
4fce290
Migrate Popover component to CSS modules
connor-baer Jun 28, 2023
f3390f2
Migrate BaseStyles component to vanilla CSS
connor-baer Jun 28, 2023
2047753
Fix bundling of legacy components
connor-baer Jun 28, 2023
d321f96
Add docs for legacy theme to legacy components
connor-baer Jun 28, 2023
3dab78b
Migrate Carousel component to CSS modules
connor-baer Jun 28, 2023
b5897c6
Migrate useFocusList hook to CSS modules
connor-baer Jun 28, 2023
3872c9b
Migrate Table components to CSS modules
connor-baer Jun 29, 2023
1418cb4
Migrate Tab components to CSS modules
connor-baer Jun 29, 2023
9656a4b
Migrate ListItem components to CSS modules
connor-baer Jun 29, 2023
8163c2b
Migrate SidePanel components to CSS modules
connor-baer Jun 29, 2023
3135d5b
Import base styles in Storybook
connor-baer Jun 29, 2023
21ae7a8
Migrate SideNavigation components to CSS modules
connor-baer Jun 29, 2023
6d0e2b0
Migrate TopNavigation components to CSS modules
connor-baer Jun 29, 2023
8d394af
Increase uniqueness of classes
connor-baer Jun 29, 2023
b301fee
Clean up private style mixins
connor-baer Jun 29, 2023
2d87993
Mark style mixins as legacy
connor-baer Jun 29, 2023
15c6eaa
Migrate Storybook components to CSS modules
connor-baer Jun 29, 2023
14fa10f
Exclude optional dependencies from bundle
connor-baer Jun 29, 2023
2583a53
Fix IconsManifest type
connor-baer Jun 29, 2023
94dbee5
Migrate Step components to CSS modules
connor-baer Jun 30, 2023
c7f4ded
Update the getting started docs
connor-baer Jul 11, 2023
e11025e
Add changeset for CSS Modules
connor-baer Jul 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/brave-bikes-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/icons': patch
---

Fixed the `IconsManifest` type.
11 changes: 11 additions & 0 deletions .changeset/lucky-monkeys-arrive.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@sumup/circuit-ui': major
---

Migrated all [stable](https://circuit.sumup.com/?path=/docs/introduction-component-lifecycle--docs) components from [Emotion.js](https://github.com/emotion-js/emotion) to [CSS Modules](https://github.com/css-modules/css-modules).

The styles are bundled and exported as a single CSS file as `@sumup/circuit-ui/styles.css`. Refer to your framework's documentation on how to include the styles globally in your application.

The CSS file includes the base styles, so the BaseStyles component has been removed.

If you are only importing [stable](https://circuit.sumup.com/?path=/docs/introduction-component-lifecycle--docs) components and aren't using Emotion.js in your app, you can remove all Emotion.js-related dependencies.
5 changes: 5 additions & 0 deletions .changeset/moody-doors-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/circuit-ui': minor
---

Improved the accessibility of the SearchInput component. The input now has the `search` type and focus is returned to the input after clearing the value.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ jobs:
- name: Lint code
run: npm run lint

# - name: Lint styles
# run: npm run lint:css
- name: Lint styles
run: npm run lint:css

- name: Run unit tests
run: npm run test:ci
Expand Down
6 changes: 0 additions & 6 deletions .storybook/components/DocsContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
// import { useEffect, useState } from 'react';
import { ThemeProvider } from '@emotion/react';
import { DocsContainer as BaseContainer } from '@storybook/addon-docs';

import * as themes from '../themes';
import { BaseStyles } from '@sumup/circuit-ui';
import { light } from '@sumup/design-tokens';

/**
* Automatically switch light/dark theme based on system preferences
Expand All @@ -30,9 +27,6 @@ const DocsContainer: typeof BaseContainer = ({ children, context }) => {

return (
<BaseContainer context={context} theme={themes.light}>
<ThemeProvider theme={light}>
<BaseStyles />
</ThemeProvider>
{children}
</BaseContainer>
);
Expand Down
54 changes: 54 additions & 0 deletions .storybook/components/Icons.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.filters {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: var(--cui-spacings-kilo);
margin-top: var(--cui-spacings-tera);
margin-bottom: var(--cui-spacings-peta);
}

.category {
margin-bottom: var(--cui-spacings-tera);
}

.list {
display: flex;
flex-wrap: wrap;
}

.wrapper {
position: relative;
width: 7.5rem;
margin-top: var(--cui-spacings-giga);
margin-bottom: var(--cui-spacings-giga);
text-align: center;
}

.size {
display: block;
font-style: italic;
color: var(--cui-fg-subtle);
}

.icon-wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 64px; /* 2 * 32px icon */
}

.icon {
max-width: 3rem;
transform: scale(2);
}

.label {
font-size: var(--cui-typography-body-two-font-size);
line-height: var(--cui-typography-body-two-line-height);
}

.badge {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-30deg);
}
116 changes: 36 additions & 80 deletions .storybook/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
*/

import { useState } from 'react';
import styled from '@emotion/styled';
import { css, ThemeProvider } from '@emotion/react';
import { light } from '@sumup/design-tokens';
import { Unstyled } from '@storybook/addon-docs';
import * as iconComponents from '@sumup/icons';
import type { IconsManifest } from '@sumup/icons';
import iconsManifest from '@sumup/icons/manifest.json';
Expand All @@ -25,19 +23,24 @@ import {
Body,
SearchInput,
Select,
typography,
BaseStyles,
Badge,
} from '@sumup/circuit-ui';
} from '../../packages/circuit-ui/index.js';
import classes from './Icons.module.css';

function groupBy(icons: IconsManifest['icons'], key: string) {
function groupBy(
icons: IconsManifest['icons'],
key: keyof IconsManifest['icons'][0],
) {
return icons.reduce((groups, icon) => {
(groups[icon[key]] = groups[icon[key]] || []).push(icon);
return groups;
}, {});
}

function sortBy(icons: IconsManifest['icons'], key: string) {
function sortBy(
icons: IconsManifest['icons'],
key: keyof IconsManifest['icons'][0],
) {
return icons.sort((iconA, iconB) => {
return iconA[key].localeCompare(iconB[key]);
});
Expand All @@ -53,61 +56,6 @@ function getComponentName(name: string) {
return pascalCased.join('');
}

const Filters = styled.div`
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: ${(p) => p.theme.spacings.kilo};
margin-top: ${(p) => p.theme.spacings.tera};
margin-bottom: ${(p) => p.theme.spacings.peta};
`;

const Category = styled.section`
margin-bottom: ${(p) => p.theme.spacings.tera};
`;

const List = styled.div`
display: flex;
flex-wrap: wrap;
`;

const Wrapper = styled.div`
width: 7.5rem;
text-align: center;
margin-top: ${(p) => p.theme.spacings.giga};
margin-bottom: ${(p) => p.theme.spacings.giga};
position: relative;
`;

const Size = styled.span`
display: block;
color: var(--cui-fg-subtle);
font-style: italic;
`;

const IconWrapper = styled.div`
display: flex;
align-items: center;
justify-content: center;
height: 64px; /* 2 * 32px icon */
`;

const iconStyles = (color: string) =>
css`
transform: scale(2);
max-width: 3rem;
color: ${color};
background-color: ${color === 'var(--cui-fg-on-strong)'
? 'var(--cui-bg-strong)'
: 'var(--cui-bg-normal)'};
`;

const badgeStyles = css`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-30deg);
`;

const Icons = () => {
const [search, setSearch] = useState('');
const [size, setSize] = useState('all');
Expand Down Expand Up @@ -148,9 +96,8 @@ const Icons = () => {
);

return (
<ThemeProvider theme={light}>
<BaseStyles />
<Filters>
<Unstyled>
<div className={classes.filters}>
<SearchInput
label="Filter icons by name"
placeholder="Search..."
Expand All @@ -171,53 +118,62 @@ const Icons = () => {
value={color}
onChange={handleColorChange}
/>
</Filters>
</div>

{activeIcons.length <= 0 ? (
<Body>No icons found</Body>
) : (
Object.entries<IconsManifest['icons']>(
groupBy(activeIcons, 'category'),
).map(([category, items]) => (
<Category key={category}>
<section key={category} className={classes.category}>
<Headline as="h3" size="three">
{category}
</Headline>
<List>
<div className={classes.list}>
{sortBy(items, 'name').map((icon) => {
const id = `${icon.name}-${icon.size}`;
const componentName = getComponentName(icon.name);
const Icon = iconComponents[componentName];
return (
<Wrapper key={id}>
<IconWrapper>
<div key={id} className={classes.wrapper}>
<div className={classes['icon-wrapper']}>
<Icon
aria-labelledby={id}
size={icon.size}
css={iconStyles(color)}
className={classes.icon}
style={{
color,
backgroundColor:
color === 'var(--cui-fg-on-strong)'
? 'var(--cui-bg-strong)'
: 'var(--cui-bg-normal)',
}}
/>
</IconWrapper>
<span id={id} css={typography('two')}>
</div>
<span id={id} className={classes.label}>
{icon.name}
{size === 'all' && <Size>{icon.size}</Size>}
{size === 'all' && (
<span className={classes.size}>{icon.size}</span>
)}
</span>
{icon.deprecation && (
<Badge
title={icon.deprecation}
variant="warning"
css={badgeStyles}
className={classes.badge}
>
Deprecated
</Badge>
)}
</Wrapper>
</div>
);
})}
</List>
</Category>
</div>
</section>
))
)}
</ThemeProvider>
</Unstyled>
);
};

Expand Down
13 changes: 5 additions & 8 deletions .storybook/components/Image.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@
* limitations under the License.
*/

import { ThemeProvider } from '@emotion/react';
import { light } from '@sumup/design-tokens';
import { Image as BaseImage, ImageProps } from '@sumup/circuit-ui';
import {
Image as BaseImage,
ImageProps,
} from '../../packages/circuit-ui/index.js';

const Image = ({ children, ...props }: ImageProps) => (
<ThemeProvider theme={light}>
<BaseImage {...props} />
</ThemeProvider>
);
const Image = ({ children, ...props }: ImageProps) => <BaseImage {...props} />;

export default Image;
8 changes: 8 additions & 0 deletions .storybook/components/Intro.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.base {
margin-bottom: var(--cui-spacings-giga);
}

.base > * {
font-size: var(--cui-typography-body-large-font-size) !important;
line-height: var(--cui-typography-body-large-line-height) !important;
}
31 changes: 6 additions & 25 deletions .storybook/components/Intro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,11 @@
* limitations under the License.
*/

import { css, ThemeProvider } from '@emotion/react';
import { BodyLarge, spacing, cx } from '@sumup/circuit-ui';
import { light } from '@sumup/design-tokens';
import { BodyLarge } from '../../packages/circuit-ui/index.js';

import type { BodyLargeProps } from '@sumup/circuit-ui';
import type { Theme } from '@sumup/design-tokens';
import type { BodyLargeProps } from '../../packages/circuit-ui/index.js';

/**
* We need this to force children to have bodyLarge typography when the Intro
* is rendered as a div.
*/
const childrenBodyLargeStyles = (theme: Theme) => css`
> * {
font-size: ${theme.typography.bodyLarge.fontSize} !important;
line-height: ${theme.typography.bodyLarge.lineHeight} !important;
}
`;
import classes from './Intro.module.css';

function Intro({
children,
Expand All @@ -38,16 +26,9 @@ function Intro({
children: BodyLargeProps['children'];
}): JSX.Element {
return (
<ThemeProvider theme={light}>
<BodyLarge
as="div"
variant="subtle"
css={cx(childrenBodyLargeStyles, spacing({ bottom: 'giga' }))}
{...props}
>
{children}
</BodyLarge>
</ThemeProvider>
<BodyLarge as="div" variant="subtle" className={classes.base} {...props}>
{children}
</BodyLarge>
);
}

Expand Down
19 changes: 19 additions & 0 deletions .storybook/components/Stack.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.base {
display: flex;
flex-direction: column;
gap: 2rem;
align-items: center;
justify-content: center;
}

@media screen and (min-width: 600px) {
.base {
flex-direction: row;
}
}

@media screen and (min-width: 600px) {
.vertical {
flex-direction: column;
}
}
Loading