feat(client): add Card header/footer, DescriptionList, and portal ContextMenu
- add Card header prop (primary/secondary variants) and footer prop (sticks to bottom) - add Breadcrumbs to all 5 pages; remove duplicate h1 headings - add pageToolbar layout for breadcrumbs + danger button aligned right - add DescriptionList component replacing raw dl/dt/dd markup; supports truncate+tooltip - rewrite ContextMenu to render dropdown via React portal to avoid clip/overflow issues - update EnvironmentCard to use Card header (primary), footer (Timestamp), and truncated DescriptionList - fix cog button contrast, square sizing, and right-edge alignment on colored header - add border to Timestamp pill for dark-mode visibility - add id badge pill styling to environment card header
This commit is contained in:
@@ -18,6 +18,7 @@ const meta: Meta<typeof Card> = {
|
||||
],
|
||||
argTypes: {
|
||||
padding: { control: 'select', options: ['sm', 'md', 'lg'] },
|
||||
headerVariant: { control: 'select', options: ['primary', 'secondary'] },
|
||||
},
|
||||
};
|
||||
export default meta;
|
||||
@@ -27,6 +28,31 @@ export const Default: Story = {
|
||||
args: { children: 'Card content goes here.', padding: 'md' },
|
||||
};
|
||||
|
||||
export const WithPrimaryHeader: Story = {
|
||||
args: {
|
||||
header: 'Section Title',
|
||||
headerVariant: 'primary',
|
||||
children: 'Card content with a primary header.',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithSecondaryHeader: Story = {
|
||||
args: {
|
||||
header: 'Section Title',
|
||||
headerVariant: 'secondary',
|
||||
children: 'Card content with a secondary header.',
|
||||
},
|
||||
};
|
||||
|
||||
export const WithFooter: Story = {
|
||||
args: {
|
||||
header: 'My Card',
|
||||
headerVariant: 'primary',
|
||||
children: 'Card body content.',
|
||||
footer: 'Last updated 2 minutes ago',
|
||||
},
|
||||
};
|
||||
|
||||
export const ScenarioCard: Story = {
|
||||
render: () => (
|
||||
<Card>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { DescriptionList } from '../../src/ui/DescriptionList/DescriptionList';
|
||||
|
||||
const meta: Meta<typeof DescriptionList> = {
|
||||
title: 'UI/DescriptionList',
|
||||
component: DescriptionList,
|
||||
parameters: { layout: 'centered' },
|
||||
tags: ['autodocs'],
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<div style={{ width: 360 }}>
|
||||
<Story />
|
||||
</div>
|
||||
),
|
||||
],
|
||||
argTypes: {
|
||||
layout: { control: 'select', options: ['inline', 'compact'] },
|
||||
},
|
||||
};
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof DescriptionList>;
|
||||
|
||||
const urlItems = [
|
||||
{ term: 'ID_URL', detail: 'https://id.example.com/' },
|
||||
{ term: 'CABINET_URL', detail: 'https://cabinet.example.com/messages' },
|
||||
{ term: 'ADMIN_URL', detail: 'https://admin.example.com/' },
|
||||
];
|
||||
|
||||
export const Inline: Story = {
|
||||
args: { items: urlItems, layout: 'inline' },
|
||||
};
|
||||
|
||||
export const Compact: Story = {
|
||||
args: { items: urlItems, layout: 'compact' },
|
||||
};
|
||||
|
||||
export const WithLinks: Story = {
|
||||
args: {
|
||||
layout: 'inline',
|
||||
items: urlItems.map(({ term, detail }) => ({
|
||||
term,
|
||||
detail: (
|
||||
<a href={detail as string} target="_blank" rel="noopener noreferrer">
|
||||
{detail}
|
||||
</a>
|
||||
),
|
||||
})),
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user