Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
"generate:compass-icons": "node scripts/gen-compass-icon-manifest.mjs",
"prebuild": "npm run generate:compass-icons && npm run build:ui",
"predev": "node scripts/ensure-compass-ui.mjs",
"predev:all": "node scripts/ensure-compass-ui.mjs",
"prepreview": "node scripts/ensure-compass-ui.mjs",
"build:ui": "npm run build --workspace=@mattermost/compass-ui",
"dev:ui": "npm run dev --workspace=@mattermost/compass-ui",
"dev:all": "npm run dev:ui & npm run dev",
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview",
Expand Down
5 changes: 5 additions & 0 deletions packages/compass-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,14 @@ From the monorepo root:

```bash
npm run build:ui # build the library
npm run dev:all # watch-rebuild UI + docs site (guidelines/specimens)
npm run storybook # component catalog on :6006
```

When editing components under `packages/compass-ui/`, Storybook reads source directly.
The docs site reads the built `dist/` output — use `dev:all` (or `dev:ui` in a second terminal
alongside `npm run dev`) so SCSS changes appear without manual rebuilds.

## Package layout

- `dist/index.js` / `dist/index.cjs` — component bundle (ESM + CJS)
Expand Down
2 changes: 1 addition & 1 deletion packages/compass-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
],
"scripts": {
"build": "vite build && sass src/styles/entry.scss dist/compass-ui.css --load-path=src/styles --no-source-map",
"dev": "vite build --watch",
"dev": "sass src/styles/entry.scss dist/compass-ui.css --load-path=src/styles --no-source-map && vite build --watch",
"typecheck": "tsc -p tsconfig.build.json --noEmit",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
align-items: center;
gap: var(--spacing-m);
min-width: 0;
padding: 18px var(--spacing-xl);
padding: var(--spacing-m) var(--spacing-xl);
}

&__intro {
Expand Down Expand Up @@ -71,5 +71,7 @@
align-items: center;
gap: var(--spacing-xs);
flex-shrink: 0;
height: var(--spacing-xxxl);
margin-right: calc(-1 * var(--spacing-xs));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { Meta, StoryObj } from '@storybook/react';
import ChannelInfoMsgHeader from './ChannelInfoMsgHeader';

const meta = {
title: 'Components/Messaging/Channel Info Msg Header',
component: ChannelInfoMsgHeader,
tags: ['autodocs'],
} satisfies Meta<typeof ChannelInfoMsgHeader>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};

export const MultipleTabs: Story = {
args: {
tabs: [
{ label: 'Spec Reviews', active: true },
{ label: 'Files' },
{ label: 'Pinned' },
],
teamName: 'Contributors',
},
};

export const AllVariants: Story = {
render: () => (
<div style={{ display: 'grid', gap: 24, maxWidth: 560 }}>
<div>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
Default
</p>
<ChannelInfoMsgHeader />
</div>
<div>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
Multiple tabs
</p>
<ChannelInfoMsgHeader
tabs={[
{ label: 'Spec Reviews', active: true },
{ label: 'Files' },
{ label: 'Pinned' },
]}
teamName="Contributors"
/>
</div>
</div>
),
};
75 changes: 75 additions & 0 deletions packages/compass-ui/src/components/Message/Message.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type { Meta, StoryObj } from '@storybook/react';
import avatarDanielle from '@/assets/avatars/Danielle Okoro.png';
import avatarLeonard from '@/assets/avatars/Leonard Riley.png';
import Divider from '../Divider/Divider';
import Message from './Message';
import messageStyles from './Message.module.scss';

const bodyTextClass = messageStyles['message__body-text'];

const meta = {
title: 'Patterns/Message',
component: Message,
tags: ['autodocs'],
} satisfies Meta<typeof Message>;

export default meta;
type Story = StoryObj<typeof meta>;

export const UserMessage: Story = {
args: {
avatarSrc: avatarLeonard,
avatarAlt: 'Leonard Riley',
username: 'Leonard Riley',
timestamp: 'Today at 9:41 AM',
children: (
<p className={bodyTextClass}>
Hey team, the new components are looking great!
</p>
),
},
};

export const BotMessage: Story = {
args: {
avatarSrc: avatarDanielle,
avatarAlt: 'Danielle Okoro',
username: 'Mattermost',
timestamp: 'Today at 9:45 AM',
isBot: true,
children: (
<p className={bodyTextClass}>
You have 3 unread messages in #general.
</p>
),
},
};

export const AllVariants: Story = {
render: () => (
<div style={{ display: 'grid', gap: 16, maxWidth: 640 }}>
<Message
avatarSrc={avatarLeonard}
avatarAlt="Leonard Riley"
username="Leonard Riley"
timestamp="Today at 9:41 AM"
>
<p className={bodyTextClass}>
Hey team, the new components are looking great!
</p>
</Message>
<Divider />
<Message
avatarSrc={avatarDanielle}
avatarAlt="Danielle Okoro"
username="Mattermost"
timestamp="Today at 9:45 AM"
isBot
>
<p className={bodyTextClass}>
You have 3 unread messages in #general.
</p>
</Message>
</div>
),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type { Meta, StoryObj } from '@storybook/react';
import MessageActions from './MessageActions';
import type { MessageActionsType } from './MessageActions';

const TYPES: MessageActionsType[] = ['Center Channel', 'RHS', 'Search Results'];

const meta = {
title: 'Components/Messaging/Message Actions',
component: MessageActions,
tags: ['autodocs'],
argTypes: {
type: { control: 'select', options: TYPES },
},
} satisfies Meta<typeof MessageActions>;

export default meta;
type Story = StoryObj<typeof meta>;

export const CenterChannel: Story = {
args: {
type: 'Center Channel',
},
};

export const RHS: Story = {
args: {
type: 'RHS',
},
};

export const SearchResults: Story = {
args: {
type: 'Search Results',
},
};

export const AllVariants: Story = {
render: () => (
<div style={{ display: 'grid', gap: 24 }}>
{TYPES.map((type) => (
<div key={type}>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
{type}
</p>
<MessageActions type={type} />
</div>
))}
</div>
),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type { Meta, StoryObj } from '@storybook/react';
import MessageHeader from './MessageHeader';

const meta = {
title: 'Components/Messaging/Message Header',
component: MessageHeader,
tags: ['autodocs'],
} satisfies Meta<typeof MessageHeader>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Normal: Story = {
args: {
username: 'Leonard Riley',
timestamp: 'Today at 9:41 AM',
},
};

export const Bot: Story = {
args: {
username: 'Mattermost',
timestamp: 'Today at 9:41 AM',
isBot: true,
},
};

export const BotCustomLabel: Story = {
args: {
username: 'PagerDuty',
timestamp: 'Yesterday at 2:15 PM',
isBot: true,
botLabel: 'APP',
},
};

export const AllVariants: Story = {
render: () => (
<div style={{ display: 'grid', gap: 16 }}>
<div>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
Normal
</p>
<MessageHeader
username="Leonard Riley"
timestamp="Today at 9:41 AM"
/>
</div>
<div>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
Bot
</p>
<MessageHeader
username="Mattermost"
timestamp="Today at 9:41 AM"
isBot
/>
</div>
<div>
<p
style={{
margin: '0 0 8px',
fontSize: 12,
color: 'rgba(var(--center-channel-color-rgb), 0.56)',
}}
>
Bot (custom label)
</p>
<MessageHeader
username="PagerDuty"
timestamp="Yesterday at 2:15 PM"
isBot
botLabel="APP"
/>
</div>
</div>
),
};
Loading
Loading