feat(ui-docs): example page layout with responsive grid
This commit is contained in:
parent
4069d2ba71
commit
dc9bd164ed
|
@ -17,6 +17,9 @@ export default defineConfig({
|
||||||
{
|
{
|
||||||
text: 'Using Components', link: '/using-components'
|
text: 'Using Components', link: '/using-components'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: 'Designing Pages', link: '/designing-pages'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
items: [
|
items: [
|
||||||
{ text: 'Activity', link: '/components/ui/activity' },
|
{ text: 'Activity', link: '/components/ui/activity' },
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
|
import { type Track, type User } from '~/types'
|
||||||
|
|
||||||
|
import Card from '~/components/ui/Card.vue'
|
||||||
|
import Layout from '~/components/ui/Layout.vue'
|
||||||
|
import Toggle from '~/components/ui/Toggle.vue'
|
||||||
|
import Spacer from '~/components/ui/layout/Spacer.vue'
|
||||||
|
import Button from '~/components/ui/Button.vue'
|
||||||
|
import Activity from '~/components/ui/Activity.vue'
|
||||||
|
|
||||||
|
const alignLeft = ref(false)
|
||||||
|
|
||||||
|
const attributes = computed(() => ({
|
||||||
|
style: alignLeft.value ? 'justify-content: start' : ''
|
||||||
|
}))
|
||||||
|
|
||||||
|
const track: Track = {
|
||||||
|
id: 0,
|
||||||
|
fid: "",
|
||||||
|
|
||||||
|
title: 'Some lovely track',
|
||||||
|
description: {
|
||||||
|
content_type: 'text/markdown',
|
||||||
|
text: `**New:** Music for the eyes!`
|
||||||
|
},
|
||||||
|
cover: {
|
||||||
|
uuid: "",
|
||||||
|
urls: {
|
||||||
|
original: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
|
medium_square_crop: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
|
large_square_crop: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tags: ["example"],
|
||||||
|
uploads: [],
|
||||||
|
downloads_count: 1927549377,
|
||||||
|
artist_credit: [{
|
||||||
|
artist: {
|
||||||
|
id: 0,
|
||||||
|
fid: "",
|
||||||
|
|
||||||
|
name: "The Artist",
|
||||||
|
description: {
|
||||||
|
content_type: 'text/markdown',
|
||||||
|
text: `I'm a musician based on the internet.
|
||||||
|
|
||||||
|
Find all my music on [Funkwhale](https://funkwhale.audio)!`},
|
||||||
|
tags: [],
|
||||||
|
|
||||||
|
content_category: 'music',
|
||||||
|
albums: [],
|
||||||
|
tracks_count: 1,
|
||||||
|
attributed_to: {
|
||||||
|
id: 0,
|
||||||
|
summary: "",
|
||||||
|
preferred_username: "User12345",
|
||||||
|
full_username: "User12345",
|
||||||
|
is_local: false,
|
||||||
|
domain: "myDomain.io"
|
||||||
|
},
|
||||||
|
is_local: false,
|
||||||
|
is_playable: true
|
||||||
|
},
|
||||||
|
credit: "",
|
||||||
|
joinphrase: " and ",
|
||||||
|
index: 22
|
||||||
|
}],
|
||||||
|
disc_number: 7,
|
||||||
|
|
||||||
|
listen_url: "https://funkwhale.audio",
|
||||||
|
creation_date: "12345",
|
||||||
|
attributed_to: {
|
||||||
|
id: 0,
|
||||||
|
summary: "",
|
||||||
|
preferred_username: "User12345",
|
||||||
|
full_username: "User12345",
|
||||||
|
is_local: false,
|
||||||
|
domain: "myDomain.io"
|
||||||
|
},
|
||||||
|
|
||||||
|
is_playable: true,
|
||||||
|
is_local: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const user: User = {
|
||||||
|
id: 12,
|
||||||
|
avatar: {
|
||||||
|
uuid: "",
|
||||||
|
urls: {
|
||||||
|
original: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
|
medium_square_crop: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
|
||||||
|
large_square_crop: 'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
email: "user12345@example.org",
|
||||||
|
summary: { text: "Hi! I'm Example from The Internet.", content_type: "text" },
|
||||||
|
username: "user12345",
|
||||||
|
full_username: "user12345",
|
||||||
|
instance_support_message_display_date: "?",
|
||||||
|
funkwhale_support_message_display_date: "?",
|
||||||
|
is_superuser: true,
|
||||||
|
privacy_level: "everyone"
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
# Designing Pages
|
||||||
|
|
||||||
|
## Grid
|
||||||
|
|
||||||
|
::: details Default widths
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The page grid consists of 46px wide tracks, separated by 32px wide gaps.
|
||||||
|
|
||||||
|
### Responsivity
|
||||||
|
|
||||||
|
- Cards and Activities snap to the grid columns. They have intrinsic widths, expressed in the number of columns they span. For Card, it is 3 and for Activity, it is 4.
|
||||||
|
- On a typical laptop screen, you will have 4 albums or 3 activities side-by-side. On a typical mobile screen, you will have 1 medium card or 2 small ones in a row.
|
||||||
|
- The remaining space is evenly distributed.
|
||||||
|
- Title rows align with the content below them.
|
||||||
|
|
||||||
|
Resize the window to observe how the items move.
|
||||||
|
|
||||||
|
<Layout flex>
|
||||||
|
<Toggle v-model="alignLeft" />
|
||||||
|
Click Toggle to left-align the layout.
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
grid="auto / repeat(auto-fit, calc(46px _ 3 + 32px _ 2))"
|
||||||
|
v-bind="attributes"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<!-- The title row's width is a multiple of 3 rows -->
|
||||||
|
<Layout flex no-gap
|
||||||
|
style="grid-column: 1 / -1; align-self: baseline;"
|
||||||
|
>
|
||||||
|
<!-- Set distance between baseline and previous row -->
|
||||||
|
<Spacer v
|
||||||
|
:size="64"
|
||||||
|
style="outline:1px solid red; align-self: baseline;"
|
||||||
|
/>
|
||||||
|
<!-- Flexible row content -->
|
||||||
|
<!-- Note that the `h3` uses its padding to create the 24px bottom gap -->
|
||||||
|
<h3 style="align-self: baseline; padding:0 0 24px 10px; margin:0;">
|
||||||
|
Albums
|
||||||
|
</h3>
|
||||||
|
<Spacer grow />
|
||||||
|
<Button ghost thin auto align-self="baseline"
|
||||||
|
style="grid-column:-1;"
|
||||||
|
>
|
||||||
|
Show all
|
||||||
|
</Button>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
</Layout>
|
||||||
|
<Layout solid default
|
||||||
|
style="position:relative;"
|
||||||
|
grid="auto / repeat(auto-fit, 46px)"
|
||||||
|
v-bind="attributes"
|
||||||
|
>
|
||||||
|
<Card small title="Relatively Long Album Name">
|
||||||
|
Artist Name
|
||||||
|
13 tracks
|
||||||
|
</Card>
|
||||||
|
<Card small title="Relatively Long Album Name">
|
||||||
|
Artist Name
|
||||||
|
13 tracks
|
||||||
|
</Card>
|
||||||
|
<Card small title="Relatively Long Album Name">
|
||||||
|
Artist Name
|
||||||
|
13 tracks
|
||||||
|
</Card>
|
||||||
|
<Card small title="Relatively Long Album Name">
|
||||||
|
Artist Name
|
||||||
|
13 tracks
|
||||||
|
</Card>
|
||||||
|
<Card small title="Relatively Long Album Name">
|
||||||
|
Artist Name
|
||||||
|
13 tracks
|
||||||
|
</Card>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
<Layout
|
||||||
|
grid="auto / repeat(auto-fit, calc(46px _ 4 + 32px _ 3))"
|
||||||
|
v-bind="attributes"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
<Layout flex no-gap
|
||||||
|
style="grid-column: 1 / -1; align-self: baseline;"
|
||||||
|
>
|
||||||
|
<!-- Set distance between baseline and previous row -->
|
||||||
|
<Spacer v
|
||||||
|
:size="64"
|
||||||
|
style="outline:1px solid red; align-self: baseline;"
|
||||||
|
/>
|
||||||
|
<!-- Flexible row content -->
|
||||||
|
<!-- Note that the `h3` uses its padding to create the 24px bottom gap -->
|
||||||
|
<h3 style="align-self: baseline; padding:0 0 24px 10px; margin:0;">
|
||||||
|
Tracks
|
||||||
|
</h3>
|
||||||
|
<Spacer grow />
|
||||||
|
<Button ghost thin auto align-self="baseline"
|
||||||
|
style="grid-column:-1;"
|
||||||
|
>
|
||||||
|
Show all
|
||||||
|
</Button>
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
</Layout>
|
||||||
|
<Layout solid default
|
||||||
|
style="position:relative;"
|
||||||
|
grid="auto / repeat(auto-fit, 46px)"
|
||||||
|
v-bind="attributes"
|
||||||
|
>
|
||||||
|
<Activity :track="track" :user="user" />
|
||||||
|
<Activity :track="track" :user="user" />
|
||||||
|
<Activity :track="track" :user="user" />
|
||||||
|
</Layout>
|
||||||
|
|
||||||
|
## Navigation
|
||||||
|
|
||||||
|
When most of the screen changes, users perceive it as a page navigation. They will expect the "back" button to bring them to the precious screen. In addition, they may expect the URL to contain the current page for sharing.
|
||||||
|
|
||||||
|
This makes a component a "page". In this sense, modals are pages.
|
||||||
|
|
||||||
|
Not everything we want to share with the Url replaces most of the screen. What about switching a filter?
|
|
@ -29,4 +29,9 @@ import Spacer from '../src/components/ui/layout/Spacer.vue'
|
||||||
Check out the design system on our Penpot.
|
Check out the design system on our Penpot.
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card to="designing-pages"
|
||||||
|
title="Page design"
|
||||||
|
style="width:min-content"
|
||||||
|
/>
|
||||||
|
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
Loading…
Reference in New Issue