@menumalsuite/design-system 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/MButton/MButton.mdx +67 -0
- package/app/components/MButton/MButton.stories.ts +36 -0
- package/app/components/MHeader/MHeader.mdx +59 -0
- package/app/components/MHeader/MHeader.stories.ts +26 -0
- package/app/components/MPage/MPage.mdx +56 -0
- package/app/components/{Page.stories.ts → MPage/MPage.stories.ts} +10 -10
- package/nuxt.config.ts +1 -1
- package/package.json +1 -1
- package/app/components/Button.stories.ts +0 -36
- package/app/components/Header.stories.ts +0 -26
- /package/app/components/{Button.vue → MButton/MButton.vue} +0 -0
- /package/app/components/{Header.vue → MHeader/MHeader.vue} +0 -0
- /package/app/components/{Page.vue → MPage/MPage.vue} +0 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as ButtonStories from './MButton.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={ButtonStories} />
|
|
5
|
+
|
|
6
|
+
# Button
|
|
7
|
+
|
|
8
|
+
Core interactive element for actions and navigation.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
- **Primary** — main page action, one per screen
|
|
13
|
+
- **Secondary** — secondary, alternative or less urgent actions
|
|
14
|
+
- **Large** — prominent CTAs, hero sections
|
|
15
|
+
- **Small** — toolbars, tables, compact spaces
|
|
16
|
+
|
|
17
|
+
## Variants
|
|
18
|
+
|
|
19
|
+
<Canvas of={ButtonStories.Primary} />
|
|
20
|
+
<Canvas of={ButtonStories.Secondary} />
|
|
21
|
+
|
|
22
|
+
## Sizes
|
|
23
|
+
|
|
24
|
+
<Canvas of={ButtonStories.Large} />
|
|
25
|
+
<Canvas of={ButtonStories.Small} />
|
|
26
|
+
|
|
27
|
+
## Props
|
|
28
|
+
|
|
29
|
+
<Controls />
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
Basic button:
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<MButton label="Save" primary @click="handleSave" />
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Secondary action:
|
|
40
|
+
|
|
41
|
+
```vue
|
|
42
|
+
<MButton label="Cancel" @click="handleCancel" />
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Navigation — pushes route via `useRouter`:
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<MButton label="Go to dashboard" to="/dashboard" />
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
API call — fires `$fetch` on click, shows inline loading/ok/error:
|
|
52
|
+
|
|
53
|
+
```vue
|
|
54
|
+
<MButton label="Submit" apiUrl="/api/submit" primary />
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Small in a table row:
|
|
58
|
+
|
|
59
|
+
```vue
|
|
60
|
+
<MButton label="Edit" size="small" @click="edit(row.id)" />
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- `to` triggers internal navigation via `useRouter`
|
|
66
|
+
- `apiUrl` fires a `$fetch` on click and displays loading/ok/error state
|
|
67
|
+
- `backgroundColor` overrides the theme color — use with caution
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { fn } from "storybook/test";
|
|
3
|
+
import MButton from "./MButton.vue";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/MButton",
|
|
7
|
+
component: MButton,
|
|
8
|
+
// tags: ['autodocs'],
|
|
9
|
+
argTypes: {
|
|
10
|
+
size: { control: "select", options: ["small", "medium", "large"] },
|
|
11
|
+
backgroundColor: { control: "color" },
|
|
12
|
+
},
|
|
13
|
+
args: {
|
|
14
|
+
primary: false,
|
|
15
|
+
onClick: fn(),
|
|
16
|
+
},
|
|
17
|
+
} satisfies Meta<typeof MButton>;
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const Primary: Story = {
|
|
23
|
+
args: { primary: true, label: "Button" },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const Secondary: Story = {
|
|
27
|
+
args: { primary: false, label: "Button" },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const Large: Story = {
|
|
31
|
+
args: { label: "Button", size: "large" },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const Small: Story = {
|
|
35
|
+
args: { label: "Button", size: "small" },
|
|
36
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as HeaderStories from './MHeader.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={HeaderStories} />
|
|
5
|
+
|
|
6
|
+
# Header
|
|
7
|
+
|
|
8
|
+
Main navigation bar of the application.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Global layout component — place in `app.vue` or the main layout. One instance per page.
|
|
13
|
+
|
|
14
|
+
## Variants
|
|
15
|
+
|
|
16
|
+
<Canvas of={HeaderStories.LoggedIn} />
|
|
17
|
+
<Canvas of={HeaderStories.LoggedOut} />
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
<Controls />
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
In `app.vue` or a layout file:
|
|
26
|
+
|
|
27
|
+
```vue
|
|
28
|
+
<template>
|
|
29
|
+
<MHeader
|
|
30
|
+
:user="authUser"
|
|
31
|
+
@login="openLoginModal"
|
|
32
|
+
@logout="signOut"
|
|
33
|
+
@create-account="openSignupModal"
|
|
34
|
+
/>
|
|
35
|
+
<slot />
|
|
36
|
+
</template>
|
|
37
|
+
|
|
38
|
+
<script setup>
|
|
39
|
+
const authUser = useCurrentUser()
|
|
40
|
+
</script>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Logged-out state:
|
|
44
|
+
|
|
45
|
+
```vue
|
|
46
|
+
<MHeader :user="null" @login="handleLogin" @create-account="handleSignup" />
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Logged-in state:
|
|
50
|
+
|
|
51
|
+
```vue
|
|
52
|
+
<MHeader :user="{ name: 'Jane Doe' }" @logout="handleLogout" />
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Notes
|
|
56
|
+
|
|
57
|
+
- Handles three events internally: `login`, `logout`, `createAccount`
|
|
58
|
+
- The `user` prop is `null` when unauthenticated
|
|
59
|
+
- Internal buttons use `<MButton>` from the design system
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { fn } from "storybook/test";
|
|
3
|
+
import MHeader from "./MHeader.vue";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/MHeader",
|
|
7
|
+
component: MHeader,
|
|
8
|
+
parameters: { layout: "fullscreen" },
|
|
9
|
+
args: {
|
|
10
|
+
onLogin: fn(),
|
|
11
|
+
onLogout: fn(),
|
|
12
|
+
onCreateAccount: fn(),
|
|
13
|
+
},
|
|
14
|
+
// tags: ['autodocs'],
|
|
15
|
+
} satisfies Meta<typeof MHeader>;
|
|
16
|
+
|
|
17
|
+
export default meta;
|
|
18
|
+
type Story = StoryObj<typeof meta>;
|
|
19
|
+
|
|
20
|
+
export const LoggedIn: Story = {
|
|
21
|
+
args: { user: { name: "Jane Doe" } },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const LoggedOut: Story = {
|
|
25
|
+
args: { user: null },
|
|
26
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as PageStories from './MPage.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={PageStories} />
|
|
5
|
+
|
|
6
|
+
# Page
|
|
7
|
+
|
|
8
|
+
Base page template with header and main content.
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Starting point for new pages — includes `<Header>` and manages authentication state internally.
|
|
13
|
+
|
|
14
|
+
## Variants
|
|
15
|
+
|
|
16
|
+
<Canvas of={PageStories.LoggedOut} />
|
|
17
|
+
<Canvas of={PageStories.LoggedIn} />
|
|
18
|
+
|
|
19
|
+
## Props
|
|
20
|
+
|
|
21
|
+
<Controls />
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Basic page:
|
|
26
|
+
|
|
27
|
+
```vue
|
|
28
|
+
<MPage />
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Extended with custom content via default slot:
|
|
32
|
+
|
|
33
|
+
```vue
|
|
34
|
+
<MPage>
|
|
35
|
+
<section>
|
|
36
|
+
<h2>Welcome</h2>
|
|
37
|
+
<p>Your dashboard content here.</p>
|
|
38
|
+
</section>
|
|
39
|
+
</MPage>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Inside a Nuxt layout (`layouts/default.vue`):
|
|
43
|
+
|
|
44
|
+
```vue
|
|
45
|
+
<template>
|
|
46
|
+
<MPage>
|
|
47
|
+
<slot />
|
|
48
|
+
</MPage>
|
|
49
|
+
</template>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Notes
|
|
53
|
+
|
|
54
|
+
- Manages `user` state internally — no need to pass it from outside
|
|
55
|
+
- Composes `<MHeader>` + `<MButton>` from the design system
|
|
56
|
+
- Extend with slots for page-specific content
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from
|
|
2
|
-
import { expect, userEvent, within } from
|
|
3
|
-
import
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3-vite";
|
|
2
|
+
import { expect, userEvent, within } from "storybook/test";
|
|
3
|
+
import MPage from "./MPage.vue";
|
|
4
4
|
|
|
5
5
|
const meta = {
|
|
6
|
-
title:
|
|
7
|
-
component:
|
|
8
|
-
parameters: { layout:
|
|
9
|
-
tags: ['autodocs'],
|
|
10
|
-
} satisfies Meta<typeof
|
|
6
|
+
title: "Components/MPage",
|
|
7
|
+
component: MPage,
|
|
8
|
+
parameters: { layout: "fullscreen" },
|
|
9
|
+
// tags: ['autodocs'],
|
|
10
|
+
} satisfies Meta<typeof MPage>;
|
|
11
11
|
|
|
12
12
|
export default meta;
|
|
13
13
|
type Story = StoryObj<typeof meta>;
|
|
@@ -15,12 +15,12 @@ type Story = StoryObj<typeof meta>;
|
|
|
15
15
|
export const LoggedIn: Story = {
|
|
16
16
|
play: async ({ canvasElement }: any) => {
|
|
17
17
|
const canvas = within(canvasElement);
|
|
18
|
-
const loginButton = canvas.getByRole(
|
|
18
|
+
const loginButton = canvas.getByRole("button", { name: /Log in/i });
|
|
19
19
|
await expect(loginButton).toBeInTheDocument();
|
|
20
20
|
await userEvent.click(loginButton);
|
|
21
21
|
await expect(loginButton).not.toBeInTheDocument();
|
|
22
22
|
|
|
23
|
-
const logoutButton = canvas.getByRole(
|
|
23
|
+
const logoutButton = canvas.getByRole("button", { name: /Log out/i });
|
|
24
24
|
await expect(logoutButton).toBeInTheDocument();
|
|
25
25
|
},
|
|
26
26
|
};
|
package/nuxt.config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
2
2
|
export default defineNuxtConfig({
|
|
3
3
|
devtools: { enabled: true },
|
|
4
|
-
components: [{ path: './app/components', pathPrefix: false }],
|
|
4
|
+
components: [{ path: './app/components', pathPrefix: false, global: true }],
|
|
5
5
|
vite: {
|
|
6
6
|
optimizeDeps: {
|
|
7
7
|
include: ["@vue/devtools-core", "@vue/devtools-kit"],
|
package/package.json
CHANGED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
-
import { fn } from 'storybook/test';
|
|
3
|
-
import Button from './Button.vue';
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: 'Components/Button',
|
|
7
|
-
component: Button,
|
|
8
|
-
tags: ['autodocs'],
|
|
9
|
-
argTypes: {
|
|
10
|
-
size: { control: 'select', options: ['small', 'medium', 'large'] },
|
|
11
|
-
backgroundColor: { control: 'color' },
|
|
12
|
-
},
|
|
13
|
-
args: {
|
|
14
|
-
primary: false,
|
|
15
|
-
onClick: fn(),
|
|
16
|
-
},
|
|
17
|
-
} satisfies Meta<typeof Button>;
|
|
18
|
-
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
|
|
22
|
-
export const Primary: Story = {
|
|
23
|
-
args: { primary: true, label: 'Button' },
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const Secondary: Story = {
|
|
27
|
-
args: { primary: false, label: 'Button' },
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const Large: Story = {
|
|
31
|
-
args: { label: 'Button', size: 'large' },
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const Small: Story = {
|
|
35
|
-
args: { label: 'Button', size: 'small' },
|
|
36
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
-
import { fn } from 'storybook/test';
|
|
3
|
-
import Header from './Header.vue';
|
|
4
|
-
|
|
5
|
-
const meta = {
|
|
6
|
-
title: 'Components/Header',
|
|
7
|
-
component: Header,
|
|
8
|
-
parameters: { layout: 'fullscreen' },
|
|
9
|
-
args: {
|
|
10
|
-
onLogin: fn(),
|
|
11
|
-
onLogout: fn(),
|
|
12
|
-
onCreateAccount: fn(),
|
|
13
|
-
},
|
|
14
|
-
tags: ['autodocs'],
|
|
15
|
-
} satisfies Meta<typeof Header>;
|
|
16
|
-
|
|
17
|
-
export default meta;
|
|
18
|
-
type Story = StoryObj<typeof meta>;
|
|
19
|
-
|
|
20
|
-
export const LoggedIn: Story = {
|
|
21
|
-
args: { user: { name: 'Jane Doe' } },
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export const LoggedOut: Story = {
|
|
25
|
-
args: { user: null },
|
|
26
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|