From 067bc9bd1b0c0f9a8505c2b40c0c99bb3569e42d Mon Sep 17 00:00:00 2001 From: Max Holman Date: Wed, 2 Nov 2022 23:16:01 +0800 Subject: [PATCH] feat: native buttons with icons --- lib/buttons.css.ts | 25 ++++++++++++++-- lib/buttons.tsx | 71 ++++++++++++++++++++++++++++---------------- lib/links.tsx | 24 --------------- src/buttons/page.tsx | 25 +++++++++++++++- 4 files changed, 92 insertions(+), 53 deletions(-) diff --git a/lib/buttons.css.ts b/lib/buttons.css.ts index 6a8c389..e034a81 100644 --- a/lib/buttons.css.ts +++ b/lib/buttons.css.ts @@ -1,13 +1,25 @@ import { createVar, style, styleVariants } from '@vanilla-extract/css'; +import { calc } from '@vanilla-extract/css-utils'; import { colorVariantVars, genericVars, rotate } from './theme.css.js'; export type ButtonVariant = 'standard' | 'ghost' | 'subtle' | 'transparent'; +export const iconClass = style({ + display: 'inline-flex', + height: '1em', + aspectRatio: '1/1', + alignItems: 'center', + justifySelf: 'center', +}); + const base = style({ cursor: 'pointer', borderStyle: 'solid', + display: 'flex', borderWidth: genericVars.border.weight.normal, borderRadius: genericVars.radius.standard, + flexDirection: 'row', + alignItems: 'center', padding: `${genericVars.space.small} ${genericVars.space.standard}`, textAlign: 'center', fontSize: genericVars.text.size.normal, @@ -32,6 +44,10 @@ export const compactButton = style({ fontSize: genericVars.text.size.small, }); +export const iconButtonClass = style({ + gap: `0 0.5em`, +}); + const buttonColorVar = createVar(); const variants: Record< @@ -94,7 +110,7 @@ export const buttonVariantClasses = styleVariants(variants, (variant) => [ // WARN: this is defined last so it can override other styles // with the same specificity -export const busyButton = style({ +export const busyButtonClass = style({ color: 'transparent', position: 'relative', display: 'grid', @@ -104,7 +120,7 @@ export const busyButton = style({ // borderColor: 'revert', // }, '&::before': { - height: '60%', + height: '1em', aspectRatio: '1/1', content: '""', position: 'absolute', @@ -121,3 +137,8 @@ export const busyButton = style({ }, }, }); + +export const inlineBleedClass = style({ + marginTop: calc(genericVars.space.small).negate().toString(), + marginBottom: calc(`${genericVars.space.small}`).negate().toString(), +}); diff --git a/lib/buttons.tsx b/lib/buttons.tsx index b112b97..89957ac 100644 --- a/lib/buttons.tsx +++ b/lib/buttons.tsx @@ -1,53 +1,72 @@ import { ClassValue, clsx } from 'clsx'; -import type { ButtonHTMLAttributes, FC, PropsWithChildren } from 'react'; -import type { Merge } from 'type-fest'; +import type { FC, ReactElement } from 'react'; import { - busyButton, - compactButton, + busyButtonClass, ButtonVariant, buttonVariantClasses, + compactButton, + iconButtonClass, + iconClass, + inlineBleedClass, } from './buttons.css.js'; -import { Align, inlineAlignSelf } from './layout.css.js'; +import { Box, BoxBasedComponentProps } from './core.js'; +import type { Align } from './layout.css.js'; -export type ButtonProps = { +export type ButtonCommonProps = { + className?: ClassValue; variant?: ButtonVariant; busy?: boolean; compact?: boolean; - className?: ClassValue; align?: Align; + inline?: boolean; }; +export type ButtonProps = ButtonCommonProps & { + icon?: ReactElement; +}; + +export type ButtonIconProps = ButtonCommonProps & {}; + export const Button: FC< - PropsWithChildren< - Merge< - ButtonHTMLAttributes, - { - variant?: ButtonVariant; - busy?: boolean; - compact?: boolean; - className?: ClassValue; - align?: Align; - } - > - > + BoxBasedComponentProps<'button' | 'a' | 'span', ButtonProps> > = ({ + component = 'button', variant = 'standard', - type = 'button', compact, busy, align, className, + icon, + inline, + children, ...props }) => ( - +); + +export const ButtonIcon: FC< + BoxBasedComponentProps<'button', ButtonIconProps> +> = ({ children, ...props }) => ( + ); diff --git a/lib/links.tsx b/lib/links.tsx index 50fcba2..60e4035 100644 --- a/lib/links.tsx +++ b/lib/links.tsx @@ -1,13 +1,5 @@ -import { clsx } from 'clsx'; import type { FC } from 'react'; -import { - busyButton, - buttonVariantClasses, - compactButton, -} from './buttons.css.js'; -import type { ButtonProps } from './buttons.js'; import { Box, BoxBasedComponentProps } from './core.js'; -import { inlineAlignSelf } from './layout.css.js'; import { linkStyle } from './links.css.js'; export const TextLink: FC> = ({ @@ -24,19 +16,3 @@ export const TextLink: FC> = ({ {children} ); - -export const ButtonLink: FC< - BoxBasedComponentProps<'span' | 'a', ButtonProps> -> = ({ variant = 'standard', compact, busy, align, className, ...props }) => ( - -); diff --git a/src/buttons/page.tsx b/src/buttons/page.tsx index a92def3..6f52a79 100644 --- a/src/buttons/page.tsx +++ b/src/buttons/page.tsx @@ -1,9 +1,10 @@ import type { FC } from 'react'; import { Button } from '../../lib/buttons.js'; import { Block, Inline } from '../../lib/layout.js'; -import { ButtonLink } from '../../lib/links.js'; +import { ButtonLink } from '../../lib/buttons.js'; import { Panel } from '../../lib/panel.js'; import { Heading, Text } from '../../lib/typography.js'; +import { SunIcon, CrescentMoonIcon } from '../icons.js'; export const ButtonsPage: FC = () => ( @@ -11,8 +12,15 @@ export const ButtonsPage: FC = () => ( Buttons + + + @@ -25,6 +33,21 @@ export const ButtonsPage: FC = () => ( + + Button Icons + + + + + + + + + + + + + Busy Buttons These buttons are super busy