Skip to content

Commit

Permalink
feat: add Message component
Browse files Browse the repository at this point in the history
  • Loading branch information
receter committed Jan 16, 2025
1 parent fe29390 commit bf3400f
Show file tree
Hide file tree
Showing 9 changed files with 236 additions and 0 deletions.
43 changes: 43 additions & 0 deletions packages/ui/fixtures/Message.fixture.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useValue } from "react-cosmos/client";

import { Message, Stack } from "../lib/main";

export default function LabelFixture() {
const [content] = useValue("Content", { defaultValue: "This is a message" });
const [isIcon] = useValue("Icon", { defaultValue: false });
const icon = isIcon ? "🚀" : undefined;
return (
<div style={{ padding: "1rem" }}>
<Stack>
<div>
<strong>Default:</strong>
<Message icon={icon}>{content}</Message>
</div>
<div>
<strong>Info:</strong>
<Message variant={"info"} icon={icon}>
{content}
</Message>
</div>
<div>
<strong>Success:</strong>
<Message variant={"success"} icon={icon}>
{content}
</Message>
</div>
<div>
<strong>Warning:</strong>
<Message variant={"warning"} icon={icon}>
{content}
</Message>
</div>
<div>
<strong>Error:</strong>
<Message variant={"error"} icon={icon}>
{content}
</Message>
</div>
</Stack>
</div>
);
}
16 changes: 16 additions & 0 deletions packages/ui/lib/Message/Message.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createComponent } from "../helpers";

import { renderMessage } from "./render";
import { MessageProps, useMessage } from "./useMessage";

export const Message = createComponent<MessageProps, "div">(
"div",
(hookOptions) => {
const { elementProps, elementRef, renderArgs } = useMessage(hookOptions);
return (
<div {...elementProps} ref={elementRef}>
{renderMessage(renderArgs)}
</div>
);
},
);
8 changes: 8 additions & 0 deletions packages/ui/lib/Message/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { BaseMessageProps } from "./useBaseMessage";
import type { MessageProps } from "./useMessage";

export { Message } from "./Message";
export { useMessage } from "./useMessage";
export { useBaseMessage } from "./useBaseMessage";

export type { BaseMessageProps, MessageProps };
12 changes: 12 additions & 0 deletions packages/ui/lib/Message/render.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { BaseMessageRenderArgs } from "./useBaseMessage";

export function renderMessage(args: BaseMessageRenderArgs) {
const { children, iconProps } = args;

return (
<>
{iconProps.children && <div {...iconProps} />}
{children}
</>
);
}
43 changes: 43 additions & 0 deletions packages/ui/lib/Message/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.message {
font-size: var(--sys42-message-font-size);
border-radius: var(--sys42-message-border-radius);
text-align: left;
padding: var(--sys42-spacing-xs) var(--sys42-spacing-sm);
display: flex;
align-items: center;
gap: var(--sys42-spacing-sm);
justify-content: center;
background: var(--sys42-message-background);
border: var(--sys42-message-border-width) solid
var(--sys42-message-border-color);
color: var(--sys42-message-color);
}

.icon {
flex-grow: 0;
flex-shrink: 0;
}

.message_info {
background: var(--sys42-message-background--info);
border-color: var(--sys42-message-border-color--info);
color: var(--sys42-message-color--info);
}

.message_success {
background: var(--sys42-message-background--success);
border-color: var(--sys42-message-border-color--success);
color: var(--sys42-message-color--success);
}

.message_warning {
background: var(--sys42-message-background--warning);
border-color: var(--sys42-message-border-color--warning);
color: var(--sys42-message-color--warning);
}

.message_error {
background: var(--sys42-message-background--error);
border-color: var(--sys42-message-border-color--error);
color: var(--sys42-message-color--error);
}
44 changes: 44 additions & 0 deletions packages/ui/lib/Message/useBaseMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Define specific props for the component
// If no props are needed, a interface with an empty object can be used
export type BaseMessageProps = {
icon?: React.ReactNode;
children?: React.ReactNode;
};

export type BaseMessageDraft<TTagName extends HTMLElementTagName> = {
elementProps: React.ComponentPropsWithoutRef<TTagName>;
iconProps: React.ComponentPropsWithoutRef<"div">;
};

export type BaseMessageRenderArgs = {
iconProps: React.ComponentPropsWithoutRef<"div">;
children: React.ReactNode;
};

export function useBaseMessage<TTagName extends HTMLElementTagName>(
{ props, forwardedRef }: UseComponentOptions<BaseMessageProps, TTagName>,
interceptor?: UseComponentInterceptor<TTagName, BaseMessageDraft<TTagName>>,
) {
const { icon, children, ...restProps } = props;

const draft: BaseMessageDraft<TTagName> = {
elementProps:
restProps satisfies EmptyObject as React.ComponentPropsWithoutRef<TTagName>,
iconProps: {
children: icon,
},
};

interceptor?.(draft);

const renderArgs: BaseMessageRenderArgs = {
iconProps: draft.iconProps,
children,
};

return {
elementProps: draft.elementProps,
elementRef: forwardedRef,
renderArgs,
};
}
33 changes: 33 additions & 0 deletions packages/ui/lib/Message/useMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { cn } from "@sys42/utils";

import { BaseMessageProps, useBaseMessage } from "./useBaseMessage";

import styles from "./styles.module.css";

export type MessageProps = BaseMessageProps & {
variant?: "info" | "success" | "warning" | "error";
};

export function useMessage<TTagName extends HTMLElementTagName>(
options: UseComponentOptions<MessageProps, TTagName>,
) {
const { variant, ...baseProps } = options.props;

return useBaseMessage(
{
...options,
props: baseProps satisfies ExactProps<BaseMessageProps, MessageProps>,
},
(draft) => {
draft.iconProps.className = cn(draft.iconProps.className, styles.icon);
draft.elementProps.className = cn(
draft.elementProps.className,
variant === "info" && styles.message_info,
variant === "success" && styles.message_success,
variant === "warning" && styles.message_warning,
variant === "error" && styles.message_error,
styles.message,
);
},
);
}
36 changes: 36 additions & 0 deletions packages/ui/lib/default-custom-properties.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
:root {
/* Font Size */
--sys42-font-size-xs: 0.75rem;
--sys42-font-size-sm: 0.875rem;
--sys42-font-size-md: 1rem;
--sys42-font-size-lg: 1.25rem;
--sys42-font-size-xl: 1.5rem;
--sys42-font-size-2xl: 2rem;

/* Spacing */
--sys42-spacing-2xs: 0.125rem;
--sys42-spacing-xs: 0.25rem;
Expand Down Expand Up @@ -138,6 +146,34 @@
);
--sys42-button_lg-padding-vert: calc(var(--sys42-button-padding-vert) * 1.5);

/* Message */
--sys42-message-font-size: var(--sys42-font-size-sm);
--sys42-message-border-radius: var(--sys42-border-radius-sm);
--sys42-message-background: #efedf4;
--sys42-message-border-width: 1px;
--sys42-message-border-color: transparent;
--sys42-message-color: #1b1b21;

/* Message (info) */
--sys42-message-background--info: #dfe1f9;
--sys42-message-border-color--info: transparent;
--sys42-message-color--info: #171b2c;

/* Message (success) */
--sys42-message-background--success: #c0efaf;
--sys42-message-border-color--success: transparent;
--sys42-message-color--success: #002200;

/* Message (warning) */
--sys42-message-background--warning: #ffdea3;
--sys42-message-border-color--warning: transparent;
--sys42-message-color--warning: #261900;

/* Message (error) */
--sys42-message-background--error: #ffdad6;
--sys42-message-border-color--error: transparent;
--sys42-message-color--error: #410002;

/* Input Text */
--sys42-input-text-background: #fff;
--sys42-input-text-border-radius: var(--sys42-border-radius-sm);
Expand Down
1 change: 1 addition & 0 deletions packages/ui/lib/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from "./FormField";
export * from "./FormFieldSet";
export * from "./Label";
export * from "./LabeledControl";
export * from "./Message";
export * from "./OverflowMenu";
export * from "./OverflowMenuItem";
export * from "./Radio";
Expand Down

0 comments on commit bf3400f

Please sign in to comment.