Skip to content

Commit

Permalink
✨ component library - minimalistic infrastructure (#4169)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatissJanis authored Feb 10, 2025
1 parent 5f1fadb commit 4ee70e7
Show file tree
Hide file tree
Showing 19 changed files with 522 additions and 420 deletions.
24 changes: 24 additions & 0 deletions packages/component-library/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "@actual-app/components",
"version": "0.0.1",
"license": "MIT",
"peerDependencies": {
"react": ">=18.2"
},
"dependencies": {
"@emotion/css": "^11.13.4",
"react-aria-components": "^1.4.1"
},
"devDependencies": {
"@types/react": "^18.2.0",
"react": "18.2.0"
},
"exports": {
"./icons/*": "./src/icons/*.tsx",
"./button": "./src/Button.tsx",
"./styles": "./src/styles.ts",
"./theme": "./src/theme.ts",
"./tokens": "./src/tokens.ts",
"./view": "./src/View.tsx"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { Button as ReactAriaButton } from 'react-aria-components';

import { css } from '@emotion/css';

import { AnimatedLoading } from '../../icons/AnimatedLoading';
import { styles, theme } from '../../style';

import { AnimatedLoading } from './icons/AnimatedLoading';
import { styles } from './styles';
import { theme } from './theme';
import { View } from './View';

const backgroundColor: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { forwardRef, type HTMLProps, type Ref } from 'react';

import { css, cx } from '@emotion/css';

import { type CSSProperties } from '../../style';
import { type CSSProperties } from './styles';

type ViewProps = HTMLProps<HTMLDivElement> & {
className?: string;
Expand Down
26 changes: 26 additions & 0 deletions packages/component-library/src/icons/AnimatedLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { type SVGProps } from 'react';

import { css, keyframes } from '@emotion/css';

import { SvgLoading } from './Loading';

const rotation = keyframes({
'0%': { transform: 'rotate(-90deg)' },
'100%': { transform: 'rotate(666deg)' },
});

export function AnimatedLoading(props: SVGProps<SVGSVGElement>) {
return (
<span
className={css({
animationName: rotation,
animationDuration: '1.6s',
animationTimingFunction: 'cubic-bezier(0.17, 0.67, 0.83, 0.67)',
animationIterationCount: 'infinite',
lineHeight: 0,
})}
>
<SvgLoading {...props} />
</span>
);
}
33 changes: 33 additions & 0 deletions packages/component-library/src/icons/Loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React, { type SVGProps, useState } from 'react';

export const SvgLoading = (props: SVGProps<SVGSVGElement>) => {
const { color = 'currentColor' } = props;
const [gradientId] = useState('gradient-' + Math.random());

return (
<svg {...props} viewBox="0 0 38 38" style={{ ...props.style }}>
<defs>
<linearGradient
x1="8.042%"
y1="0%"
x2="65.682%"
y2="23.865%"
id={gradientId}
>
<stop stopColor={color} stopOpacity={0} offset="0%" />
<stop stopColor={color} stopOpacity={0.631} offset="63.146%" />
<stop stopColor={color} offset="100%" />
</linearGradient>
</defs>
<g transform="translate(1 2)" fill="none" fillRule="evenodd">
<path
d="M36 18c0-9.94-8.06-18-18-18"
stroke={'url(#' + gradientId + ')'}
strokeWidth={2}
fill="none"
/>
<circle fill={color} cx={36} cy={18} r={1} />
</g>
</svg>
);
};
151 changes: 151 additions & 0 deletions packages/component-library/src/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import { keyframes } from '@emotion/css';

import { theme } from './theme';
import { tokens } from './tokens';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type CSSProperties = Record<string, any>;

const MOBILE_MIN_HEIGHT = 40;

const shadowLarge = {
boxShadow: '0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)',
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const styles: Record<string, any> = {
incomeHeaderHeight: 70,
cardShadow: '0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)',
monthRightPadding: 5,
menuBorderRadius: 4,
mobileMinHeight: MOBILE_MIN_HEIGHT,
mobileMenuItem: {
fontSize: 17,
fontWeight: 400,
paddingTop: 8,
paddingBottom: 8,
height: MOBILE_MIN_HEIGHT,
minHeight: MOBILE_MIN_HEIGHT,
},
mobileEditingPadding: 12,
altMenuMaxHeight: 250,
altMenuText: {
fontSize: 13,
},
altMenuHeaderText: {
fontSize: 13,
fontWeight: 700,
},
veryLargeText: {
fontSize: 30,
fontWeight: 600,
},
largeText: {
fontSize: 20,
fontWeight: 700,
letterSpacing: 0.5,
},
mediumText: {
fontSize: 15,
fontWeight: 500,
},
smallText: {
fontSize: 13,
},
verySmallText: {
fontSize: 12,
},
tinyText: {
fontSize: 10,
},
page: {
flex: 1,
'@media (max-height: 550px)': {
minHeight: 700, // ensure we can scroll on small screens
},
paddingTop: 8, // height of the titlebar
[`@media (min-width: ${tokens.breakpoint_small})`]: {
paddingTop: 36,
},
},
pageContent: {
paddingLeft: 2,
paddingRight: 2,
[`@media (min-width: ${tokens.breakpoint_small})`]: {
paddingLeft: 20,
paddingRight: 20,
},
},
settingsPageContent: {
padding: 20,
[`@media (min-width: ${tokens.breakpoint_small})`]: {
padding: 'inherit',
},
},
staticText: {
cursor: 'default',
userSelect: 'none',
},
shadow: {
boxShadow: '0 2px 4px 0 rgba(0,0,0,0.1)',
},
shadowLarge,
tnum: {
// eslint-disable-next-line rulesdir/typography
fontFeatureSettings: '"tnum"',
},
notFixed: { fontFeatureSettings: '' },
text: {
fontSize: 16,
// lineHeight: 22.4 // TODO: This seems like trouble, but what's the right value?
},
delayedFadeIn: {
animationName: keyframes({
'0%': { opacity: 0 },
'100%': { opacity: 1 },
}),
animationDuration: '1s',
animationFillMode: 'both',
animationDelay: '0.5s',
},
underlinedText: {
borderBottom: `2px solid`,
},
noTapHighlight: {
WebkitTapHighlightColor: 'transparent',
':focus': {
outline: 'none',
},
},
lineClamp: (lines: number) => {
return {
display: '-webkit-box',
WebkitLineClamp: lines,
WebkitBoxOrient: 'vertical',
overflow: 'hidden',
textOverflow: 'ellipsis',
wordBreak: 'break-word',
};
},
tooltip: {
padding: 5,
...shadowLarge,
borderWidth: 2,
borderRadius: 4,
borderStyle: 'solid',
borderColor: theme.tooltipBorder,
backgroundColor: theme.tooltipBackground,
color: theme.tooltipText,
overflow: 'auto',
},
popover: {
border: 'none',
backgroundColor: theme.menuBackground,
color: theme.menuItemText,
},
// Dynamically set
horizontalScrollbar: null as CSSProperties | null,
lightScrollbar: null as CSSProperties | null,
darkScrollbar: null as CSSProperties | null,
scrollbarWidth: null as number | null,
};
Loading

0 comments on commit 4ee70e7

Please sign in to comment.