Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/LexSwed/fxtrot-ui into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
LexSwed committed Dec 25, 2022
2 parents 8012775 + de4adf3 commit b40d3f7
Show file tree
Hide file tree
Showing 17 changed files with 193 additions and 420 deletions.
459 changes: 98 additions & 361 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
"description": "UI library for Fxtrot initiatives",
"version": "0.0.1",
"license": "Apache-2.0",
"type": "module",
"source": "src/lib/index.ts",
"types": "dist/index.d.ts",
"main": "./dist/fxtrot-ui.js",
"main": "./dist/fxtrot-ui.umd.js",
"module": "./dist/fxtrot-ui.es.js",
"exports": {
".": {
"import": "./dist/fxtrot-ui.es.js",
"require": "./dist/fxtrot-ui.js",
"require": "./dist/fxtrot-ui.umd.js",
"types": "./dist/index.d.ts"
},
"./tailwind.cjs": "./dist/tailwind.preset.cjs",
"./dist/style.css": "./dist/style.css"
"./styles.css": "./dist/styles.css"
},
"sideEffects": [
"*.css"
Expand Down Expand Up @@ -72,6 +71,7 @@
"@mdx-js/loader": "^2.2.1",
"@mdx-js/mdx": "^2.2.1",
"@mdx-js/react": "^2.2.1",
"@next/font": "^13.1.1",
"@next/mdx": "^13.0.7",
"@parcel/packager-ts": "^2.8.2",
"@parcel/transformer-typescript-tsc": "^2.8.2",
Expand All @@ -81,12 +81,12 @@
"@types/jest": "^29.2.4",
"@types/node": "^18.11.17",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@types/react-dom": "^18.0.10",
"@typescript-eslint/eslint-plugin": "^5.47.0",
"@typescript-eslint/parser": "^5.47.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.30.0",
"eslint-config-next": "^13.0.7",
"eslint-config-next": "^13.1.1",
"eslint-config-prettier": "^8.5.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-import": "^2.26.0",
Expand All @@ -99,7 +99,7 @@
"husky": "^8.0.1",
"jest": "^29.0.3",
"lint-staged": "^13.1.0",
"next": "^13.0.7",
"next": "^13.1.1",
"next-seo": "^5.15.0",
"parcel": "^2.8.2",
"pinst": "^3.0.0",
Expand Down
Binary file added public/fonts/FiraCode-VariableFont_wght.ttf
Binary file not shown.
Binary file added public/fonts/Inter-VariableFont_slnt,wght.ttf
Binary file not shown.
17 changes: 11 additions & 6 deletions src/lib/button/button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
white-space: nowrap;
background: transparent;
font-weight: theme('fontWeight.medium');
line-height: theme('lineHeight.none');
color: theme('colors.on-surface');
transition-property: color, box-shadow, filter, border-color, background-color, background-image;
transition-duration: 200ms;
Expand Down Expand Up @@ -214,18 +215,20 @@
Size
*/
.size--xs {
min-block-size: theme(spacing.6);
min-block-size: theme(spacing.7);
border-radius: theme('borderRadius.md');
@apply text-xs py-1 px-2;
font-size: theme('fontSize.xs');
@apply py-1 px-2;
&:where(.button--icon) {
@apply px-1;
min-inline-size: theme(spacing.6);
min-inline-size: theme(spacing.7);
}
}
.size--sm {
min-block-size: theme(spacing.8);
border-radius: theme('borderRadius.md');
@apply text-sm py-1 px-3;
font-size: theme('fontSize.sm');
@apply py-1 px-3;
&:where(.button--icon) {
@apply px-1;
min-inline-size: theme(spacing.8);
Expand All @@ -234,7 +237,8 @@
.size--md {
min-block-size: theme(spacing.10);
border-radius: theme('borderRadius.lg');
@apply text-sm py-2 px-4;
font-size: theme('fontSize.sm');
@apply py-2 px-4;
&:where(.button--icon) {
@apply px-2;
min-inline-size: theme(spacing.10);
Expand All @@ -243,7 +247,8 @@
.size--lg {
min-block-size: theme(spacing.12);
border-radius: theme('borderRadius.lg');
@apply text-base py-2 px-6;
font-size: theme('fontSize.md');
@apply py-2 px-6;
&:where(.button--icon) {
@apply px-2;
min-inline-size: theme(spacing.12);
Expand Down
1 change: 1 addition & 0 deletions src/lib/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
className={buttonCssWithDefaults(props)}
aria-label={label}
title={label}
disabled={disabled}
aria-disabled={disabled}
type={type}
ref={ref}
Expand Down
7 changes: 5 additions & 2 deletions src/lib/menu-list/menu-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ export const MenuList = ({ flow = 'column', className, ...props }: MenuListProps
);
};

type MenuListItemProps<C extends ElementType> = PolyProps<C, ListItemVariants & { disabled?: boolean }>;
type MenuListItemProps<C extends ElementType> = PolyProps<
C,
ListItemVariants & { disabled?: boolean; active?: boolean }
>;
type MenuListItemComponent = <C extends ElementType = 'span'>(props: MenuListItemProps<C>) => ReactElement | null;

export const Item: MenuListItemComponent = forwardRef(
<C extends ElementType = 'a'>(
{ as, className, disabled, onKeyDown, 'aria-current': active, ...props }: MenuListItemProps<C>,
{ as, className, disabled, onKeyDown, active, ...props }: MenuListItemProps<C>,
ref: PolyRef<C>
) => {
const Component = as || 'a';
Expand Down
4 changes: 2 additions & 2 deletions src/lib/theme-provider/default-theme.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ const defaultTheme = {
'on-surface-variant': 'hsl(215 6% 40%)',
'inverse-surface': 'hsl(225 4.1% 19.2%)',
'inverse-on-surface': 'hsl(255 15.4% 94.9%)',
'disabled': 'hsl(0deg 0% 90%)',
'on-disabled': 'hsl(204 9.1% 30%)',
'disabled': 'hsl(0deg 0% 91%)',
'on-disabled': 'hsl(204 9.1% 41%)',
},
// Tailwind default + xs and popper
boxShadow: {
Expand Down
31 changes: 20 additions & 11 deletions src/lib/theme-provider/theme-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,50 @@ import { Direction, DirectionProvider } from '@radix-ui/react-direction';
import { TooltipProvider } from '@radix-ui/react-tooltip';
import { clsx } from 'clsx';

import { useForkRef } from '../utils/hooks';
import { useForkRef, useId } from '../utils/hooks';
import type { Theme } from './types';

import styles from './theme-provider.module.css';
import { createThemeVariables } from './utils';
import defaultTheme from './default-theme.cjs';
import { createThemeVariables, mergeTheme } from './utils';

type Props = {
children?: ReactNode;
theme?: Theme;
} & ComponentProps<'div'>;

const ThemeProvider = forwardRef<HTMLDivElement, Props>(({ theme = defaultTheme, className, ...props }, propRef) => {
const ThemeProvider = forwardRef<HTMLDivElement, Props>(({ theme = {}, className, children, ...props }, propRef) => {
const rootRef = useFxtrotRootRef();
const ref = useRef<HTMLDivElement>(null);
const [direction, directionRef] = useDirection();
const refs = useForkRef<HTMLElement>(ref, directionRef, propRef);
// slice :r0: -> r0
const themeClassName = `fxtrot-ui-${useId().slice(1, -1)}`;
const css = createThemeCssText(themeClassName, theme);

return (
<rootRefContext.Provider value={rootRef.current ? rootRef : ref}>
<DirectionProvider dir={direction}>
<TooltipProvider delayDuration={400}>
<div
{...props}
// @ts-expect-error
style={{ ...Object.fromEntries(createThemeVariables(theme)), ...props.style }}
className={clsx(styles['fxtrot-ui-theme'], className)}
ref={refs}
/>
<>
<style dangerouslySetInnerHTML={{ __html: css }} />
<div {...props} className={clsx(styles['fxtrot-ui-theme'], themeClassName, className)} ref={refs}>
{children}
</div>
</>
</TooltipProvider>
</DirectionProvider>
</rootRefContext.Provider>
);
});

function createThemeCssText(className: string, theme: Theme) {
const fullTheme = mergeTheme(theme);
const css = `.${className} {${createThemeVariables(fullTheme)
.map((entry) => entry.join(':'))
.join(';')};}`.trim();
return css;
}

const rootRefContext = createContext<RefObject<HTMLElement>>({ current: null });
export const useFxtrotRootRef = () => useContext(rootRefContext);

Expand Down
3 changes: 2 additions & 1 deletion src/lib/theme-provider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type createTailwindFontVariables = (fontSize: NonNullable<Theme['fontSize
fontSize: Record<keyof Theme['fontSize'], string>;
lineHeight: Record<keyof Theme['fontSize'], string>;
};
export type toToken = (themeConfig: string, name: string) => `--fx-${string}-${string}`;

export type createTailwindVariables = (theme: Theme) => import('tailwindcss').Config;

Expand Down Expand Up @@ -135,7 +136,7 @@ export type Theme = {
fontSize?: {
'xs'?: ['0.75rem', '1rem'];
'sm'?: ['0.875rem', '1.25rem'];
'base'?: ['1rem', '1.5rem'];
'md'?: ['1rem', '1.5rem'];
'lg'?: ['1.125rem', '1.75rem'];
'xl'?: ['1.25rem', '1.75rem'];
'2xl'?: ['1.5rem', '2rem'];
Expand Down
25 changes: 25 additions & 0 deletions src/lib/theme-provider/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { ThemeColor, Theme } from './types';
import { toToken } from '../utils.cjs';
import defaultTheme from './default-theme.cjs';

/**
* Transforms passed theme colors into CSS variables map that are consumed by the components.
Expand Down Expand Up @@ -68,3 +69,27 @@ export function createThemeVariables(theme: Theme): ThemeVariableEntry[] {
}

type ThemeVariableEntry = [`--fxtrot-${string}-${string}`, string];

/**
* Takes partial theme and merges it with the default one.
*/
export function mergeTheme(theme: Theme): DeepRequired<Theme> {
const resultingTheme = { ...defaultTheme };
Object.keys(theme).forEach((themeKey) => {
const themeConfig = theme[themeKey as ThemeKey];
if (!themeConfig) return;
// @ts-expect-error 2022 can't type Object.keys properly in TypeScript :/
resultingTheme[themeKey] = { ...defaultTheme[themeKey] };
Object.keys(themeConfig).forEach((configKey) => {
// @ts-expect-error
resultingTheme[themeKey][configKey] = themeConfig[configKey];
});
});
// @ts-expect-error defaultTheme has colors as strings and not HSL, as JSDoc doesn't support @satisfies yet
return resultingTheme;
}

type ThemeKey = NonNullable<keyof Theme>;
type DeepRequired<T> = {
[K in keyof T]: Required<DeepRequired<T[K]>>;
};
4 changes: 1 addition & 3 deletions src/lib/utils.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
/**
* @param {string} themeConfig - Type of the token: color, scale, fontSize
* @param {string} name - Name of the token
* @return {string}
* @type {import('./theme-provider/types').toToken}
*/
function toToken(themeConfig, name) {
return `--fx-${themeConfig}-${name.split('.').join('\\.')}`;
Expand Down
2 changes: 1 addition & 1 deletion src/pages-helpers/MainLayout/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const LinksList = ({ links }: { links: DocEntry[] }) => {
{links.map((item) => {
return (
<Link href={item.href} passHref legacyBehavior key={item.title}>
<MenuList.Item aria-current={item.href === router.pathname}>{item.title}</MenuList.Item>
<MenuList.Item active={item.href === router.pathname}>{item.title}</MenuList.Item>
</Link>
);
})}
Expand Down
2 changes: 1 addition & 1 deletion src/pages-helpers/MultilineCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const MultilineCode = ({ code, language }: Props) => {
{tokens.map((line, i) => {
const lineProps = getLineProps({ line, key: i });
return (
<line {...lineProps} className={clsx('table-row text-sm', lineProps.className)} key={i}>
<line {...lineProps} className={clsx('table-row text-sm', lineProps.className)}>
<span className="table-cell select-none text-end opacity-50 pr-4">{i + 1}</span>
<span className="table-cell">
{line.map((token, key) => (
Expand Down
19 changes: 18 additions & 1 deletion src/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import './globals.css';
import localFont from '@next/font/local';

import { NextSeo } from 'next-seo';
import { ThemeProvider } from '@fxtrot/ui';

import { MdxProvider } from 'src/pages-helpers/MdxProvider';
import type { AppProps } from 'next/dist/shared/lib/router/router';

const Inter = localFont({
src: '../../public/fonts/Inter-VariableFont_slnt,wght.ttf',
fallback: ['-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, sans-serif'],
weight: 'variable',
variable: '--fxtrot-fontFamily-sans',
});
const FiraCode = localFont({
src: '../../public/fonts/FiraCode-VariableFont_wght.ttf',
fallback: ['Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace'],
weight: 'variable',
variable: '--fxtrot-fontFamily-mono',
});

export default function App(props: AppProps) {
const { Component, pageProps } = props;
return (
Expand Down Expand Up @@ -39,7 +53,10 @@ export default function App(props: AppProps) {
},
]}
/>
<ThemeProvider>
<ThemeProvider
className={[Inter.variable, FiraCode.variable].join(' ')}
theme={{ fontFamily: { sans: Inter.style.fontFamily, mono: FiraCode.style.fontFamily } }}
>
<MdxProvider>
<Component {...pageProps} />
</MdxProvider>
Expand Down
23 changes: 0 additions & 23 deletions src/pages/_document.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/pages/components/MenuList.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ title: MenuList
].map(({ icon, label, disabled, className }) => (
<MenuList.Item
key={label}
selected={selected === label}
active={selected === label}
disabled={disabled}
onClick={() => setSelected(label)}
className={className}
Expand Down

0 comments on commit b40d3f7

Please sign in to comment.