Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Chat: ny small-variant, justert design, forbedret UU #2048

Merged
merged 19 commits into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/two-beans-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@navikt/ds-css": minor
"@navikt/ds-react": minor
"@navikt/aksel-stylelint": minor
---

Chat: ny small-variant, forbedret UU, samt andre visuelle justeringer
KenAJoh marked this conversation as resolved.
Show resolved Hide resolved
45 changes: 30 additions & 15 deletions @navikt/core/css/chat.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
.navds-chat {
display: flex;
align-items: flex-end;
gap: var(--a-spacing-4);
padding-right: var(--a-spacing-16);
gap: var(--a-spacing-3);
max-width: 40.75rem;
}

.navds-chat--right {
flex-direction: row-reverse;
padding-right: 0;
padding-left: var(--a-spacing-16);
}

.navds-chat__bubble-wrapper {
Expand All @@ -26,15 +24,20 @@

.navds-chat__avatar {
align-items: center;
background: var(--ac-chat-avatar-bg, var(--a-bg-subtle));
color: var(--ac-chat-avatar-color, var(--a-text-default));
box-shadow: var(--a-shadow-xsmall);
background-color: var(--ac-chat-avatar-bg, var(--a-bg-subtle));
border: 1px solid var(--ac-chat-border-color, var(--a-border-subtle));
border-radius: var(--a-border-radius-full);
color: var(--ac-chat-avatar-color, var(--a-text-default));
display: flex;
flex-shrink: 0;
justify-content: center;
overflow: hidden;
height: 3rem;
width: 3rem;
padding: 0.441em 0.29em;
height: 2.5rem;
width: 2.5rem;
font-size: 17px;
letter-spacing: 0.0187em;
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
}

.navds-chat__avatar svg {
Expand All @@ -44,11 +47,11 @@
}

.navds-chat__bubble {
padding: 1rem;
box-shadow: var(--a-shadow-small);
padding: var(--a-spacing-4);
box-shadow: var(--a-shadow-xsmall);
width: fit-content;
max-width: 37.5rem;
background-color: var(--ac-chat-bubble-bg, var(--a-bg-subtle));
KenAJoh marked this conversation as resolved.
Show resolved Hide resolved
border: 1px solid var(--ac-chat-border-color, var(--a-border-subtle));
border-radius: var(--a-border-radius-xlarge);
border-bottom-left-radius: 2px;
display: flex;
Expand All @@ -61,11 +64,27 @@
border-bottom-right-radius: 2px;
}

.navds-chat--small .navds-chat__bubble {
padding: var(--a-spacing-3);
}

.navds-chat--info .navds-chat__bubble,
.navds-chat--info .navds-chat__avatar {
background-color: var(--a-surface-info-subtle);
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
}

.navds-chat--neutral .navds-chat__bubble,
.navds-chat--neutral .navds-chat__avatar {
background-color: var(--a-bg-default);
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
}

.navds-chat__top-text {
color: var(--ac-chat-top-text, var(--a-text-default));
display: flex;
gap: var(--a-spacing-2);
align-items: baseline;
font-weight: normal;
margin: 0;
}

.navds-chat--right .navds-chat__top-text {
Expand All @@ -87,7 +106,3 @@
.navds-chat--right .navds-chat__top-text--left {
align-self: flex-start;
}

.navds-chat__name {
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
font-weight: var(--a-font-weight-bold);
}
1 change: 1 addition & 0 deletions @navikt/core/css/tokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"--ac-button-tertiary-neutral-active-hover-bg": "--a-surface-neutral-active"
},
"chat": {
"--ac-chat-border-color": "--a-border-subtle",
"--ac-chat-avatar-bg": "--a-bg-subtle",
"--ac-chat-avatar-color": "--a-text-default",
"--ac-chat-bubble-bg": "--a-bg-subtle",
Expand Down
14 changes: 9 additions & 5 deletions @navikt/core/react/src/chat/Bubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface BubbleProps extends HTMLAttributes<HTMLDivElement> {
timestamp?: string;
/**
* Background color on bubble
* @deprecated Use `variant` on Chat instead
*/
backgroundColor?: string;
/**
Expand Down Expand Up @@ -46,17 +47,20 @@ const Bubble = forwardRef<HTMLDivElement, BubbleProps>(
{...rest}
>
{(timestamp || name) && (
<div
<h3
className={cl(
`navds-chat__top-text`,
toptextPosition && `navds-chat__top-text--${toptextPosition}`
)}
>
{name && <Detail className="navds-chat__name">{name}</Detail>}
{timestamp && (
<Detail className="navds-chat__timestamp">{timestamp}</Detail>
{name && <Detail as="span">{name}</Detail>}
{name && timestamp && (
<Detail as="span" aria-hidden>
&bull;
</Detail>
)}
</div>
{timestamp && <Detail as="span">{timestamp}</Detail>}
</h3>
)}
{children}
</div>
Expand Down
116 changes: 68 additions & 48 deletions @navikt/core/react/src/chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import React, { forwardRef, HTMLAttributes } from "react";
import cl from "clsx";
import Bubble, { BubbleProps } from "./Bubble";
import { BodyLong, BodyShort } from "../typography";
import { BodyLong } from "../typography";

export const POSITIONS = ["left", "right"] as const;
export const SIZES = ["medium", "small"] as const;
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved

export interface ChatProps extends HTMLAttributes<HTMLDivElement> {
/**
Expand All @@ -17,27 +20,40 @@ export interface ChatProps extends HTMLAttributes<HTMLDivElement> {
*/
timestamp?: string;
/**
* Avatar for messenger. Regular text for initials works to
* Avatar for messenger. Regular text for initials works too, but it will be hidden for screen readers.
*/
avatar?: React.ReactNode;
/**
* Changes background color on avatar and bubbles.
* Avoid using the same background as the surface behind Chat.
* @default "subtle"
*/
avatar: React.ReactNode;
variant?: "subtle" | "info" | "neutral";
/**
* Background color on bubbles
* @deprecated Use `variant` instead
*/
backgroundColor?: string;
/**
* Background color for avatar
* @deprecated Use `variant` instead
*/
avatarBgColor?: string;
/**
* Positions avatar and Bubbles
* Positions avatar and bubbles
* @default "left"
*/
position?: "left" | "right";
position?: (typeof POSITIONS)[number];
/**
* Hoizontal position of toptext
* @default Same as chat
* @default Same as position
*/
toptextPosition?: (typeof POSITIONS)[number];
/**
* Affects padding and font size in bubbles
* @default "medium"
*/
toptextPosition?: "left" | "right";
size?: (typeof SIZES)[number];
}

interface ChatComponent
Expand All @@ -53,18 +69,19 @@ interface ChatComponent
}

/**
* A component for displaying chat messages.
* A component for communicating dialogs between two parties.
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/chat)
* @see 🏷️ {@link ChatProps}
*
* @example
* ```jsx
* <Chat>
* <Chat.Bubble avatar="A" name="Alice">Hello!</Chat.Bubble>
* <Chat avatar="A" name="Alice" timestamp="01.01.21 14:00">
* <Chat.Bubble>Hello!</Chat.Bubble>
* <Chat.Bubble>How can I help you?</Chat.Bubble>
* </Chat>
* <Chat>
* <Chat.Bubble avatar="B" name="Bob">Hi there!</Chat.Bubble>
* <Chat avatar="B" name="Bob" timestamp="01.01.21 14:01" position="right">
* <Chat.Bubble>Hi there!</Chat.Bubble>
* </Chat>
* ```
*/
Expand All @@ -77,51 +94,54 @@ export const Chat = forwardRef<HTMLDivElement, ChatProps>(
timestamp,
avatar,
position = "left",
variant = "subtle",
avatarBgColor,
backgroundColor,
toptextPosition,
size = "medium",
...rest
},
}: ChatProps,
HalvorHaugan marked this conversation as resolved.
Show resolved Hide resolved
ref
) => {
return (
<div
ref={ref}
className={cl(
"navds-chat",
className,
`navds-chat--${position} navds-chat--top-text-${
toptextPosition ?? position
}`
)}
{...rest}
>
<BodyShort
as="div"
) => (
<div
ref={ref}
className={cl(
"navds-chat",
className,
`navds-chat--${position}`,
`navds-chat--top-text-${toptextPosition ?? position}`,
`navds-chat--${size}`,
`navds-chat--${variant}`
)}
{...rest}
>
{avatar && (
<div
className="navds-chat__avatar"
aria-hidden
style={{ backgroundColor: avatarBgColor }}
>
{avatar}
</BodyShort>
<ol className="navds-chat__bubble-wrapper">
{React.Children.map(children, (child, i) => {
if (React.isValidElement(child)) {
return (
<BodyLong as="li">
{React.cloneElement(child, {
name: name && i === 0 ? name : undefined,
timestamp: timestamp && i === 0 ? timestamp : undefined,
backgroundColor,
...child.props,
})}
</BodyLong>
);
}
})}
</ol>
</div>
);
}
</div>
)}
<ol className="navds-chat__bubble-wrapper">
{React.Children.map(children, (child, i) => {
if (React.isValidElement(child)) {
return (
<BodyLong as="li" size={size}>
{React.cloneElement(child, {
name: name && i === 0 ? name : undefined,
timestamp: timestamp && i === 0 ? timestamp : undefined,
backgroundColor,
...child.props,
})}
</BodyLong>
);
}
})}
</ol>
</div>
)
) as ChatComponent;

Chat.Bubble = Bubble;
Expand Down
Loading