Skip to content
Merged
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
21 changes: 20 additions & 1 deletion playground/components/NuxtBadge.story.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<template>
<Story title="Badge">
<Story
title="Badge"
:layout="{ width: '33%' }"
>
<Variant title="Default">
<UBadge>Badge</UBadge>
</Variant>
Expand All @@ -9,5 +12,21 @@
Badge
</UBadge>
</Variant>

<Variant title="Size">
<UBadge size="lg">
Badge
</UBadge>
</Variant>

<Variant title="Color">
<UBadge color="secondary">
Badge
</UBadge>
</Variant>

<Variant title="Label">
<UBadge label="A label" />
</Variant>
</Story>
</template>
101 changes: 89 additions & 12 deletions src/runtime/components/Story.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<div
class="story-content"
:class="tvStory().content({ class: [classes?.content, storyClasses.content] })"
:data-layout="layout.type"
>
<template v-if="hasVariants">
<slot />
Expand Down Expand Up @@ -68,13 +69,20 @@ const tvStory = tv({
},
})

interface Layout {
type?: 'grid' | 'wrap' | 'none'
cols?: number
width?: string
}

defineOptions({
name: 'StoryContainer',
})

defineProps<{
const props = defineProps<{
title?: string
classes?: ComponentSlotClasses
layout?: Layout
}>()

const config = useRuntimeConfig()
Expand All @@ -91,6 +99,45 @@ const hasVariants = computed(() => {
)
})

// layout properties
const layout = computed(() => {
// defaults
const layout: Layout = {
type: 'none',
cols: undefined,
width: undefined,
}

// columns
if (props.layout) {
const { cols, width } = props.layout

// grid
if (cols) {
layout.type = 'grid'
layout.cols = cols
}

else if (width) {
// grid
if (width.endsWith('%')) {
const percent = Number.parseInt(width)
layout.type = 'grid'
layout.cols = Math.round(1 / (percent / 100))
}

// wrap
else if (width.endsWith('px')) {
layout.type = 'wrap'
layout.width = width
}
}
}

// return
return layout
})

async function openInEditor() {
if (!story) {
return
Expand All @@ -105,7 +152,7 @@ async function openInEditor() {
}
</script>

<style scoped>
<style>
[data-bedtime-theme]:not([data-bedtime-theme='false']) {
.story-container {
padding: var(--story-container-padding);
Expand All @@ -119,16 +166,6 @@ async function openInEditor() {
letter-spacing: var(--story-title-letter-spacing);
}

.story-content {
margin: var(--story-content-margin);
display: var(--story-content-display);
gap: var(--story-content-grid-gap);
grid-template-columns: var(--story-content-grid-template-columns);
& > * + * {
margin-top: var(--story-content-gap);
}
}

.story-actions {
align-items: var(--story-actions-align-content);
display: var(--story-actions-display);
Expand All @@ -137,10 +174,50 @@ async function openInEditor() {

.story-header {
display: var(--story-header-display);
margin-bottom: var(--story-header-margin-bottom);
gap: var(--story-header-gap);
& > * + * {
flex-shrink: 0;
}
}
}

.story-content[data-layout="none"] {
& > .variant-container + .variant-container {
margin-top: 1.5rem; /* aldi space-y-4 */
}
}

.story-content[data-layout="grid"] {
--gap: 1.5rem;
--columns: v-bind('layout.cols');
--numGaps: calc(var(--columns) - 1);
--allGaps: calc(var(--numGaps) * var(--gap));

display: flex;
flex-wrap: wrap;
gap: var(--gap);

.variant-container {
width: calc(
(100% - var(--allGaps)) / var(--columns)
);
}
}

.story-content[data-layout="wrap"] {
--gap: 1.5rem;

display: flex;
flex-wrap: wrap;
gap: var(--gap);

.variant-container {
width: v-bind('layout.width');
}
}

.story-content > .variant-container {
overflow: hidden;
}
</style>
3 changes: 3 additions & 0 deletions src/runtime/components/Variant.vue
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ watch(() => route.hash, (newHash) => {

.variant-header {
display: var(--variant-header-display);
justify-content: var(--variant-header-justify);
gap: var(--variant-header-gap);
align-items: var(--variant-actions-align-content);
}
Expand All @@ -155,6 +156,8 @@ watch(() => route.hash, (newHash) => {
font-size: var(--variant-title-font-size);
font-weight: var(--variant-title-font-weight);
letter-spacing: var(--variant-title-letter-spacing);
white-space: nowrap;
overflow: hidden;
}
}
</style>
7 changes: 6 additions & 1 deletion src/runtime/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@
--story-actions-display: flex;
--story-actions-gap: 0.5rem;
--story-border-color: #e5e5e5;

--story-container-padding: 0;
--story-container-width: 100%;
--story-content-margin: 1rem 0 0 0;
--story-content-display: block;
--story-content-gap: 1rem;
--story-content-grid-template-columns: ;
--story-content-grid-gap: ;

--story-header-align-content: center;
--story-header-display: flex;
--story-header-gap: 0.5rem;
--story-header-margin-bottom: 1rem;

--story-title-font-size: 1.2rem;
--story-title-font-weight: 500;
--story-title-letter-spacing: -0.02em;
Expand All @@ -35,6 +39,7 @@
--variant-content-guideline-border: 0;
--variant-header-align-content: center;
--variant-header-display: flex;
--variant-header-justify: space-between;
--variant-header-gap: 0.5rem;
--variant-title-font-size: 1rem;
--variant-title-font-weight: 500;
Expand All @@ -51,7 +56,7 @@
/* Stories Layout */
--stories-layout-height: 100vh;
--stories-main-bg-color: #fff;
--stories-main-padding: 1rem;
--stories-main-padding: 1.5rem;
--stories-sidebar-bg-color: #f8f8f8;
--stories-sidebar-border: 1px solid #e5e5e5;
--stories-sidebar-padding: 1rem;
Expand Down
Loading