diff --git a/libs/web/shared/ui/src/lib/box/box.props.ts b/libs/web/shared/ui/src/lib/box/box.props.ts index a3f9e39..4db65a7 100644 --- a/libs/web/shared/ui/src/lib/box/box.props.ts +++ b/libs/web/shared/ui/src/lib/box/box.props.ts @@ -9,10 +9,26 @@ export type BoxSize = (typeof BoxSizes)[number]; export type BoxWidth = BoxSize; export type BoxHeight = BoxSize; +export const BoxAlignments = ['top-left', 'top', 'top-right', 'left', 'center', 'right', 'bottom-left', 'bottom', 'bottom-right'] as const; +export type BoxAlignment = (typeof BoxAlignments)[number]; + +export const BoxDirections = ['horizontal', 'vertical'] as const; +export type BoxDirection = (typeof BoxDirections)[number]; + +export const BoxGaps = ['none', '0.5', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '12', '16', '18', '20', '24'] as const; +export type BoxGap = (typeof BoxGaps)[number]; + +export const BoxBorders = ['none', 'full', '1', '2', '3', '4', '5', '6'] as const; +export type BoxBorder = (typeof BoxBorders)[number]; + type NativeDiv = QwikIntrinsicElements['div']; export interface BoxProps extends NativeDiv { variant?: BoxVariant; width?: BoxWidth; height?: BoxHeight; + align?: BoxAlignment; + direction?: BoxDirection; + gap?: BoxGap; + border?: BoxBorder; } diff --git a/libs/web/shared/ui/src/lib/box/box.stories.tsx b/libs/web/shared/ui/src/lib/box/box.stories.tsx index ff23bcb..a62248f 100644 --- a/libs/web/shared/ui/src/lib/box/box.stories.tsx +++ b/libs/web/shared/ui/src/lib/box/box.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from 'storybook-framework-qwik'; import { Box } from './box'; -import { BoxVariants, type BoxProps, BoxSizes } from './box.props'; +import { BoxVariants, type BoxProps, BoxSizes, BoxAlignments, BoxDirections, BoxGaps, BoxBorders } from './box.props'; const meta = { component: Box, @@ -21,6 +21,26 @@ const meta = { options: BoxSizes, control: { type: 'inline-radio' }, }, + align: { + description: 'Box alignment', + options: BoxAlignments, + control: { type: 'inline-radio' }, + }, + direction: { + description: 'Box direction', + options: BoxDirections, + control: { type: 'inline-radio' }, + }, + gap: { + description: 'Box gap', + options: BoxGaps, + control: { type: 'inline-radio' }, + }, + border: { + description: 'Box border', + options: BoxBorders, + control: { type: 'inline-radio' }, + }, }, } satisfies Meta; @@ -30,13 +50,22 @@ export default meta; export const Primary = { args: { - variant: 'secondary', - width: '10', - height: '10', + variant: 'surface', + width: '24', + height: '24', + align: 'center', + direction: 'vertical', + gap: '0.5', }, render: (props) => (
- + +

Mercury

+

Venus

+

Earth

+

Mars

+

Jupyter

+
), } satisfies Story; diff --git a/libs/web/shared/ui/src/lib/box/box.tsx b/libs/web/shared/ui/src/lib/box/box.tsx index f2b67b3..2415deb 100644 --- a/libs/web/shared/ui/src/lib/box/box.tsx +++ b/libs/web/shared/ui/src/lib/box/box.tsx @@ -1,8 +1,8 @@ import { Slot, component$ } from '@builder.io/qwik'; -import type { BoxProps, BoxVariant, BoxWidth } from './box.props'; +import type { BoxAlignment, BoxBorder, BoxDirection, BoxGap, BoxProps, BoxVariant, BoxWidth } from './box.props'; export const Box = component$((props) => { - const { variant = 'surface', width = 'full', height = 'full', ...rest } = props; + const { variant = 'surface', width = 'full', height = 'full', align = 'left', direction = 'vertical', gap = 'none', border = 'none', ...rest } = props; const Variants = { primary: 'bg-primary-container text-primary-container-on', @@ -54,8 +54,56 @@ export const Box = component$((props) => { '24': 'h-96', } satisfies { [K in BoxWidth]: string }; + const Alignments = { + 'top-left': 'items-start justify-start', + 'top': direction === 'horizontal' ? 'items-start justify-center' : 'items-center justify-start', + 'top-right': direction === 'horizontal' ? 'items-start justify-end' : 'justify-start items-end', + 'left': direction === 'horizontal' ? 'items-center justify-start' : 'justify-center items-start', + 'center': 'items-center justify-center', + 'right': direction === 'horizontal' ? 'items-center justify-end' : 'justify-center items-end', + 'bottom-left': direction === 'horizontal' ? 'items-end justify-start' : 'items-start justify-end', + 'bottom': direction === 'horizontal' ? 'items-end justify-center' : 'justify-end items-center', + 'bottom-right': 'items-end justify-end', + } satisfies { [K in BoxAlignment]: string }; + + const Directions = { + horizontal: 'flex-row', + vertical: 'flex-col', + } satisfies { [K in BoxDirection]: string }; + + const Gaps = { + none: 'gap-0', + '0.5': 'gap-2', + '1': 'gap-4', + '2': 'gap-8', + '3': 'gap-12', + '4': 'gap-16', + '5': 'gap-20', + '6': 'gap-24', + '7': 'gap-28', + '8': 'gap-32', + '9': 'gap-36', + '10': 'gap-40', + '12': 'gap-48', + '16': 'gap-64', + '18': 'gap-72', + '20': 'gap-80', + '24': 'gap-96', + } satisfies { [K in BoxGap]: string }; + + const Borders = { + none: 'rounded-none', + full: 'rounded-full', + '1': 'rounded', + '2': 'rounded-md', + '3': 'rounded-lg', + '4': 'rounded-xl', + '5': 'rounded-2xl', + '6': 'rounded-3xl', + } satisfies { [K in BoxBorder]: string }; + return ( -
+
); diff --git a/libs/web/shared/ui/src/lib/button/button.tsx b/libs/web/shared/ui/src/lib/button/button.tsx index 05d2606..abae514 100644 --- a/libs/web/shared/ui/src/lib/button/button.tsx +++ b/libs/web/shared/ui/src/lib/button/button.tsx @@ -4,18 +4,38 @@ import type { ButtonProps, ButtonShape, ButtonSize, ButtonVariant } from './butt export const Button = component$((props) => { const { size = 'base', variant = 'primary', rounded = false, disabled = false, ...rest } = props; + const currentVariant = disabled ? 'disabled' : variant; + const cursor = disabled ? 'cursor-default' : 'cursor-pointer'; + const shape = rounded ? 'rounded' : 'base'; + const Sizes = { small: 'px-2 py-1 text-sm', base: 'px-4 py-2 text-lg', large: 'px-6 py-4 text-xl', } satisfies { [K in ButtonSize]: string }; - const Variants = { - primary: 'bg-primary text-primary-on', - secondary: 'bg-secondary text-secondary-on', - tertiary: 'bg-tertiary text-tertiary-on', - error: 'bg-error text-error-on', - disabled: 'bg-surface-on/[.12] text-surface-on/[.38] cursor-default', + const ContainerVariants = { + primary: 'bg-primary', + secondary: 'ring-1 ring-outline', + tertiary: 'bg-tertiary', + error: 'bg-error', + disabled: 'bg-surface-on/[.12]', + } satisfies { [K in ButtonVariant | 'disabled']: string }; + + const LabelVariants = { + primary: 'text-primary-on', + secondary: 'text-primary', + tertiary: 'text-tertiary-on', + error: 'text-error-on', + disabled: 'text-surface-on/[.38]', + } satisfies { [K in ButtonVariant | 'disabled']: string }; + + const StateLayerVariants = { + primary: 'group-hover/button:bg-surface-variant-on/[.08] group-active/button:bg-surface-variant-on/[.10] group-focus/button:bg-surface-variant-on/[.10]', + secondary: 'group-hover/button:bg-primary/[.08] group-active/button:bg-primary/[.10] group-focus/button:bg-primary/[.10]', + tertiary: 'bg-tertiary-on/[.08]', + error: 'bg-error-on/[.08]', + disabled: 'bg-surface-on/[.12]', } satisfies { [K in ButtonVariant | 'disabled']: string }; const Shapes = { @@ -24,8 +44,12 @@ export const Button = component$((props) => { } satisfies { [K in ButtonShape]: string }; return ( - ); });