Avis du studio DA du 03/11 (07h00) et relecture de 8ccdda3 :
- règle du perché : il faut au-dessus de l'arête un vide au moins égal à la hauteur
de l'oiseau, sinon il va en marge ou derrière la carte. Les perchés entre cartes
rapprochées (numérique, logiciel-libre, économique, sommaire du livre, commande,
citoyenne, événement) passent en marge, derrière, ou partent ;
- productions-collectives : 8 oiseaux ramenés à 4, sans colonne ni chevauchement.
Les oiseaux retirés vont sur des pages qui en avaient peu : monnaie-libre
(boulangère, vigneronne), tarifs-eau (potier), décision (tisserand),
cloud-libre (imprimeuse 3D). Les 61 restent rendus ;
- pas trois oiseaux sur la même verticale (commande, numérique) ;
- au téléphone, l'oiseau de la page se tient au bout de la ligne de l'intitulé ;
- seuil 1024 pour un perché dont le bloc n'a de vide au-dessus qu'en deux colonnes
(accordéoniste et factrice de l'accueil) ;
- numerique/[slug] : les oiseaux des sections larges tiennent dans 152 px de marge
à 1200 px ;
- en-tête : de 768 à 1023 px, boutons resserrés au lieu d'un débordement ; le
logotype du kit ne change pas.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
153 lines
4.9 KiB
Vue
153 lines
4.9 KiB
Vue
<script setup lang="ts">
|
|
// A bird of the librodrome placed on its block (composition of 03/11, docs/consignes-yvv.md):
|
|
// it stands on a real edge of the page, next to the content its trade is about.
|
|
// The host block is the positioning context: position relative, overflow visible.
|
|
//
|
|
// Poses
|
|
// perche on the block's top edge (bottom: 100%), x with left / right
|
|
// marge-g beside the block, on its left; feet at the block's bottom, raised by `bottom`
|
|
// marge-d the same, on its right
|
|
// derriere large and pale, behind the block (z-index -1): only what sticks out shows.
|
|
// Needs a stacking context above the block (isolation: isolate) and a block
|
|
// that creates none itself (no z-index, transform, opacity, filter).
|
|
// libre placed only by left / right / top / bottom (an empty area next to its block)
|
|
//
|
|
// Birds in the margin, behind a block or free need room around the column: they show from
|
|
// 1200 px wide, the perched ones from 768 px (`seuil` overrides, for instance 1024 for a perched
|
|
// bird whose block has no void above it until the grid splits in two); under 768 px, only a
|
|
// bird marked `mobile`.
|
|
// A perched bird needs, above its edge, a void at least as tall as itself (DA rule of 03/11);
|
|
// where blocks stand close, the bird goes in the margin or behind the block.
|
|
//
|
|
// Drawing rules of the studio DA (kit README, §2.5): one colour (currentColor), proportions
|
|
// intact and never cropped, 72 px wide at least, opacity 0.18-0.28 next to text and 0.10-0.14
|
|
// large behind a card, mirror allowed except for the calligraphe and the typographe.
|
|
// Birds standing on an edge do not move; only the one behind a card drifts a little (Yvv, 03/11).
|
|
import { OISEAUX } from '~/utils/oiseaux'
|
|
|
|
type Pose = 'perche' | 'marge-g' | 'marge-d' | 'derriere' | 'libre'
|
|
|
|
const props = withDefaults(defineProps<{
|
|
nom: string
|
|
pose?: Pose
|
|
/** Width in px: S 72-90, M 108-156, L 200-250 */
|
|
w?: number
|
|
left?: string
|
|
right?: string
|
|
top?: string
|
|
bottom?: string
|
|
/** Gap between the block and a bird in the margin */
|
|
ecart?: string
|
|
retourne?: boolean
|
|
/** Shown under 768 px (one bird per page at most) */
|
|
mobile?: boolean
|
|
/** Shown under 768 px only: the phone place of a bird placed elsewhere on wider screens */
|
|
mobileSeul?: boolean
|
|
/** Narrowest window (px) where the bird shows: 1200 by default for the margin, behind
|
|
* and free poses, 768 for a perched bird */
|
|
seuil?: 768 | 1024 | 1200
|
|
ton?: 'primary' | 'accent'
|
|
op?: number
|
|
}>(), { pose: 'perche', w: 80, ecart: '2.5rem', ton: 'primary' })
|
|
|
|
/** These two write and compose from left to right: never mirrored */
|
|
const NO_MIRROR = new Set(['calligraphe', 'typographe'])
|
|
|
|
const sol = computed(() => OISEAUX[props.nom]?.sol ?? 5)
|
|
|
|
const style = computed(() => {
|
|
const s: Record<string, string> = { 'width': `${Math.max(72, props.w)}px`, '--sol': `${sol.value}%` }
|
|
if (props.pose === 'perche') s.bottom = '100%'
|
|
if (props.pose === 'marge-g') s.right = `calc(100% + ${props.ecart})`
|
|
if (props.pose === 'marge-d') s.left = `calc(100% + ${props.ecart})`
|
|
if (props.pose === 'marge-g' || props.pose === 'marge-d') s.bottom = '0px'
|
|
for (const k of ['left', 'right', 'top', 'bottom'] as const) {
|
|
if (props[k] !== undefined) s[k] = props[k]!
|
|
}
|
|
if (props.op !== undefined) s.opacity = String(props.op)
|
|
return s
|
|
})
|
|
|
|
const classes = computed(() => [
|
|
'oiseau-pose',
|
|
`oiseau-pose--${props.pose}`,
|
|
{
|
|
'oiseau-pose--retourne': props.retourne && !NO_MIRROR.has(props.nom),
|
|
'oiseau-pose--mobile': props.mobile || props.mobileSeul,
|
|
'oiseau-pose--mobile-seul': props.mobileSeul,
|
|
'oiseau-pose--large': (props.seuil ?? (props.pose === 'perche' ? 768 : 1200)) >= 1200,
|
|
'oiseau-pose--moyen': props.seuil === 1024,
|
|
'oiseau-pose--accent': props.ton === 'accent',
|
|
},
|
|
])
|
|
</script>
|
|
|
|
<template>
|
|
<UiOiseau :nom="nom" :class="classes" :style="style" :data-oiseau="nom" :data-pose="pose" />
|
|
</template>
|
|
|
|
<style scoped>
|
|
.oiseau-pose {
|
|
position: absolute;
|
|
z-index: 1;
|
|
pointer-events: none;
|
|
color: hsl(var(--color-primary));
|
|
opacity: 0.24;
|
|
/* The drawing's ground line lands on the edge */
|
|
transform: translateY(var(--sol));
|
|
}
|
|
|
|
.oiseau-pose--accent {
|
|
color: hsl(var(--color-accent));
|
|
}
|
|
|
|
.oiseau-pose--perche {
|
|
opacity: 0.28;
|
|
}
|
|
|
|
.oiseau-pose--derriere {
|
|
z-index: -1;
|
|
opacity: 0.12;
|
|
animation: oiseau-derive 12s ease-in-out infinite alternate;
|
|
}
|
|
|
|
.oiseau-pose--retourne {
|
|
scale: -1 1;
|
|
}
|
|
|
|
@keyframes oiseau-derive {
|
|
from { translate: 0 0; }
|
|
to { translate: 0 -6px; }
|
|
}
|
|
|
|
@media (max-width: 1199px) {
|
|
.oiseau-pose--large {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1023px) {
|
|
.oiseau-pose--moyen {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 768px) {
|
|
.oiseau-pose--mobile-seul {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 767px) {
|
|
.oiseau-pose:not(.oiseau-pose--mobile) {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.oiseau-pose--derriere {
|
|
animation: none;
|
|
}
|
|
}
|
|
</style>
|