Skip to content

Commit c5cdc06

Browse files
✨(ats-presentation) add content container components (#687)
* 🐛(ats-presentation) restore missing dsfr token * ✨(ats-presentation) add card component * ✨(ats-presentation) add dialog component * ✨(ats-presentation) add drawer component --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 32bff44 commit c5cdc06

8 files changed

Lines changed: 1598 additions & 0 deletions

File tree

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
import type { ComponentPropsAndSlots, StoryObj } from '@storybook/vue3'
2+
import CspButton from '@/components/base/CspButton/CspButton.vue'
3+
import CspCard from '@/components/base/CspCard/CspCard.vue'
4+
5+
type CspCardProps = ComponentPropsAndSlots<typeof CspCard>
6+
7+
const meta = {
8+
title: 'Éléments/Génériques/CspCard',
9+
component: CspCard,
10+
tags: ['autodocs'],
11+
parameters: {
12+
controls: {
13+
include: ['variant', 'size', 'as', 'title', 'titleAs', 'description', 'href'],
14+
},
15+
docs: {
16+
description: {
17+
component: 'Carte générique pour présenter du contenu avec un titre, une description et des actions associées.',
18+
},
19+
},
20+
},
21+
argTypes: {
22+
variant: {
23+
control: { type: 'radio' },
24+
options: ['default', 'alt'] satisfies NonNullable<CspCardProps['variant']>[],
25+
description: 'Style visuel.',
26+
table: {
27+
type: { summary: 'default | alt' },
28+
defaultValue: { summary: 'default' },
29+
},
30+
},
31+
size: {
32+
control: { type: 'radio' },
33+
options: ['sm', 'md', 'lg'] satisfies NonNullable<CspCardProps['size']>[],
34+
description: 'Taille de la carte : ajuste padding, interlignes et typographie.',
35+
table: {
36+
type: { summary: 'sm | md | lg' },
37+
defaultValue: { summary: 'md' },
38+
},
39+
},
40+
as: {
41+
control: { type: 'radio' },
42+
options: ['article', 'section', 'div'] satisfies NonNullable<CspCardProps['as']>[],
43+
description: 'Élément racine rendu.',
44+
table: {
45+
type: { summary: 'string' },
46+
defaultValue: { summary: 'article' },
47+
},
48+
},
49+
title: {
50+
control: { type: 'text' },
51+
description: 'Titre de la carte. Surclassé par le slot `title`.',
52+
table: {
53+
type: { summary: 'string | null' },
54+
defaultValue: { summary: 'null' },
55+
},
56+
},
57+
titleAs: {
58+
control: { type: 'radio' },
59+
options: ['h2', 'h3', 'h4', 'h5', 'h6'] satisfies NonNullable<CspCardProps['titleAs']>[],
60+
description: 'Niveau de titre rendu (accessibilité).',
61+
table: {
62+
type: { summary: 'h2 | h3 | h4 | h5 | h6' },
63+
defaultValue: { summary: 'h3' },
64+
},
65+
},
66+
description: {
67+
control: { type: 'text' },
68+
description: 'Description de la carte. Surclassée par le slot `description`.',
69+
table: {
70+
type: { summary: 'string | null' },
71+
defaultValue: { summary: 'null' },
72+
},
73+
},
74+
href: {
75+
control: { type: 'text' },
76+
description: 'Active le motif « carte cliquable » : le titre devient un lien couvrant toute la carte.',
77+
table: {
78+
type: { summary: 'string' },
79+
},
80+
},
81+
default: { control: false, table: { disable: true } },
82+
start: { control: false, table: { disable: true } },
83+
end: { control: false, table: { disable: true } },
84+
footer: { control: false, table: { disable: true } },
85+
class: { control: false, table: { disable: true } },
86+
style: { control: false, table: { disable: true } },
87+
key: { control: false, table: { disable: true } },
88+
ref: { control: false, table: { disable: true } },
89+
ref_for: { control: false, table: { disable: true } },
90+
ref_key: { control: false, table: { disable: true } },
91+
},
92+
args: {
93+
variant: 'default',
94+
size: 'md',
95+
as: 'article',
96+
title: 'Titre de la carte',
97+
titleAs: 'h3',
98+
description: 'Description courte qui précise le contenu de la carte.',
99+
href: undefined,
100+
},
101+
render: (args: CspCardProps) => ({
102+
components: { CspButton, CspCard },
103+
setup() {
104+
return { args }
105+
},
106+
template: `
107+
<div class="max-w-xl">
108+
<CspCard v-bind="args">
109+
<p>Contenu principal de la carte, placé dans le slot par défaut.</p>
110+
111+
<template #footer>
112+
<CspButton label="Action" variant="primary" />
113+
<CspButton label="Secondaire" variant="secondary" />
114+
</template>
115+
</CspCard>
116+
</div>
117+
`,
118+
}),
119+
}
120+
121+
export default meta
122+
type Story = StoryObj<CspCardProps>
123+
124+
const VARIANTS = ['default', 'alt'] as const
125+
const SIZES = ['sm', 'md', 'lg'] as const
126+
127+
export const Default: Story = {}
128+
129+
export const TitleAndDescription: Story = {
130+
render: (args: CspCardProps) => ({
131+
components: { CspCard },
132+
setup() {
133+
return { args }
134+
},
135+
template: `
136+
<div class="max-w-xl">
137+
<CspCard v-bind="args" />
138+
</div>
139+
`,
140+
}),
141+
}
142+
143+
export const WithLink: Story = {
144+
args: {
145+
title: 'Libellé du lien',
146+
description: 'Description courte de la carte cliquable.',
147+
href: '#',
148+
},
149+
render: (args: CspCardProps) => ({
150+
components: { CspCard },
151+
setup() {
152+
return { args }
153+
},
154+
template: `
155+
<div class="max-w-xl">
156+
<CspCard v-bind="args">
157+
<p>La carte entière est cliquable : titre bleu et flèche signalent l'interactivité.</p>
158+
</CspCard>
159+
</div>
160+
`,
161+
}),
162+
}
163+
164+
export const WithStartAndEnd: Story = {
165+
render: (args: CspCardProps) => ({
166+
components: { CspCard },
167+
setup() {
168+
return { args }
169+
},
170+
template: `
171+
<div class="max-w-xl">
172+
<CspCard v-bind="args">
173+
<template #start>
174+
<!-- Placeholder : remplacer par de futurs CspTag / CspBadge -->
175+
<span class="csp-card-story-placeholder">Tag</span>
176+
<span class="csp-card-story-placeholder">Badge</span>
177+
</template>
178+
179+
<p>Corps de la carte décrivant le contenu principal.</p>
180+
181+
<template #end>
182+
<!-- Placeholder : informations méta (date, lieu, durée…) -->
183+
<span>Information méta</span>
184+
</template>
185+
</CspCard>
186+
</div>
187+
188+
<style>
189+
.csp-card-story-placeholder {
190+
display: inline-flex;
191+
align-items: center;
192+
padding: 0.125rem 0.5rem;
193+
border-radius: 0.25rem;
194+
font-size: 0.75rem;
195+
background-color: var(--background-alt-blue-france);
196+
color: var(--text-action-high-blue-france);
197+
}
198+
</style>
199+
`,
200+
}),
201+
}
202+
203+
export const Composition: Story = {
204+
render: (args: CspCardProps) => ({
205+
components: { CspButton, CspCard },
206+
setup() {
207+
return { args }
208+
},
209+
template: `
210+
<div class="max-w-xl">
211+
<CspCard v-bind="args" :title="null" :description="null">
212+
<template #title>
213+
Titre via slot
214+
</template>
215+
<template #description>
216+
Description via slot, pouvant contenir du <strong>balisage</strong>.
217+
</template>
218+
219+
<p>Corps de la carte libre.</p>
220+
221+
<template #footer>
222+
<CspButton label="Libellé" variant="primary" />
223+
</template>
224+
</CspCard>
225+
</div>
226+
`,
227+
}),
228+
}
229+
230+
export const Variants: Story = {
231+
render: (args: CspCardProps) => ({
232+
components: { CspCard },
233+
setup() {
234+
return { variants: VARIANTS, args }
235+
},
236+
template: `
237+
<div class="flex flex-col gap-6 max-w-xl">
238+
<CspCard
239+
v-for="v in variants"
240+
:key="v"
241+
v-bind="args"
242+
:variant="v"
243+
:title="v"
244+
description="Contenu de démonstration."
245+
/>
246+
</div>
247+
`,
248+
}),
249+
}
250+
251+
export const Sizes: Story = {
252+
render: (args: CspCardProps) => ({
253+
components: { CspCard },
254+
setup() {
255+
return { sizes: SIZES, args }
256+
},
257+
template: `
258+
<div class="flex flex-col gap-6 max-w-xl">
259+
<CspCard
260+
v-for="s in sizes"
261+
:key="s"
262+
v-bind="args"
263+
:size="s"
264+
:title="'size: ' + s"
265+
description="Contenu de démonstration."
266+
/>
267+
</div>
268+
`,
269+
}),
270+
}

0 commit comments

Comments
 (0)