Skip to content

Commit 89a8d81

Browse files
committed
✨ Add DeviceMockup block
1 parent d35c82b commit 89a8d81

13 files changed

+358
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ import { Accordion } from 'webcoreui/react'
272272
## Blocks
273273

274274
- [BlogCard](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/BlogCard)
275+
- [ComponentMap](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ComponentMap)
276+
- [DeviceMockup](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/DeviceMockup)
275277
- [ErrorPage](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/ErrorPage)
276278
- [FAQ](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/FAQ)
277279
- [GridWithIcons](https://github.com/Frontendland/webcoreui/tree/main/src/blocks/GridWithIcons)

public/img/placeholder4.png

93 KB
Loading

public/img/placeholder5.png

67.9 KB
Loading

public/img/placeholder6.png

79.2 KB
Loading

public/img/placeholder7.png

116 KB
Loading

public/img/placeholder8.png

56 KB
Loading
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
import type { DeviceMockupProps } from './deviceMockup'
3+
import styles from './device-mockup.module.scss'
4+
5+
interface Props extends DeviceMockupProps {}
6+
7+
const {
8+
type,
9+
url,
10+
showButtons = true,
11+
closeButtonColor,
12+
maximizeButtonColor,
13+
minimizeButtonColor,
14+
className
15+
} = Astro.props
16+
17+
const classes = [
18+
styles.mockup,
19+
className
20+
]
21+
22+
const getColor = (color: string | undefined) => color
23+
? `background:${color};`
24+
: null
25+
---
26+
27+
<div class:list={classes}>
28+
{(type === 'desktop' && (showButtons || url)) && (
29+
<div class={styles.actions}>
30+
{showButtons && (
31+
<div class={styles.container}>
32+
<span class={styles.button} style={getColor(closeButtonColor)} />
33+
<span class={styles.button} style={getColor(maximizeButtonColor)} />
34+
<span class={styles.button} style={getColor(minimizeButtonColor)} />
35+
</div>
36+
)}
37+
{url && (
38+
<div class:list={[styles.url, !showButtons && styles.full]}>
39+
{url}
40+
</div>
41+
)}
42+
</div>
43+
)}
44+
<slot />
45+
</div>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<script lang="ts">
2+
import { classNames } from 'webcoreui'
3+
4+
import type { DeviceMockupProps } from './deviceMockup'
5+
import styles from './device-mockup.module.scss'
6+
7+
export let type: DeviceMockupProps['type'] = null
8+
export let url: DeviceMockupProps['url'] = ''
9+
export let showButtons: DeviceMockupProps['showButtons'] = true
10+
export let closeButtonColor: DeviceMockupProps['closeButtonColor'] = ''
11+
export let maximizeButtonColor: DeviceMockupProps['maximizeButtonColor'] = ''
12+
export let minimizeButtonColor: DeviceMockupProps['minimizeButtonColor'] = ''
13+
export let className: DeviceMockupProps['className'] = ''
14+
15+
const classes = classNames([
16+
styles.mockup,
17+
className
18+
])
19+
20+
const getColor = (color: string | undefined) => color
21+
? `background:${color};`
22+
: null
23+
</script>
24+
25+
<div class={classes}>
26+
{#if type === 'desktop' && (showButtons || url)}
27+
<div class={styles.actions}>
28+
{#if showButtons}
29+
<div class={styles.container}>
30+
<span class={styles.button} style={getColor(closeButtonColor)} />
31+
<span class={styles.button} style={getColor(maximizeButtonColor)} />
32+
<span class={styles.button} style={getColor(minimizeButtonColor)} />
33+
</div>
34+
{/if}
35+
{#if url}
36+
<div class={classNames([
37+
styles.url,
38+
!showButtons && styles.full
39+
])}>
40+
{url}
41+
</div>
42+
{/if}
43+
</div>
44+
{/if}
45+
46+
<slot />
47+
</div>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react'
2+
import { classNames } from 'webcoreui'
3+
4+
import type { ReactDeviceMockupProps } from './deviceMockup'
5+
import styles from './device-mockup.module.scss'
6+
7+
const DeviceMockup = ({
8+
type,
9+
url,
10+
showButtons = true,
11+
closeButtonColor,
12+
maximizeButtonColor,
13+
minimizeButtonColor,
14+
className,
15+
children
16+
}: ReactDeviceMockupProps) => {
17+
const classes = classNames([
18+
styles.mockup,
19+
className
20+
])
21+
22+
const containerClasses = classNames([
23+
styles.container,
24+
'flex xs items-center'
25+
])
26+
27+
const getColor = (color: string | undefined) => color
28+
? { background: color }
29+
: undefined
30+
31+
return (
32+
<div className={classes}>
33+
{(type === 'desktop' && (showButtons || url)) && (
34+
<div className={styles.actions}>
35+
{showButtons && (
36+
<div className={containerClasses} style={{ minHeight: 15 }}>
37+
<span className={styles.button} style={getColor(closeButtonColor)} />
38+
<span className={styles.button} style={getColor(maximizeButtonColor)} />
39+
<span className={styles.button} style={getColor(minimizeButtonColor)} />
40+
</div>
41+
)}
42+
{url && (
43+
<div className={classNames([styles.url, !showButtons && styles.full])}>
44+
{url}
45+
</div>
46+
)}
47+
</div>
48+
)}
49+
{children}
50+
</div>
51+
)
52+
}
53+
54+
export default DeviceMockup
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
@use 'webcoreui/config' as *;
2+
3+
.mockup {
4+
@include background(primary-70);
5+
@include border(6px, primary-50);
6+
@include border-radius(xl);
7+
@include visibility(hidden);
8+
}
9+
10+
.actions {
11+
@include background(primary-50);
12+
@include spacing(pl-sm, pr-sm, pb-xs);
13+
@include layout(flex, xl);
14+
15+
.container {
16+
min-width: fit-content
17+
}
18+
19+
.button {
20+
@include background(primary-20);
21+
@include size(10px);
22+
@include visibility(inline-block);
23+
@include border-radius(maxs);
24+
}
25+
26+
.url {
27+
@include background(primary-40);
28+
@include typography(md, primary-20, center);
29+
@include border-radius();
30+
@include size('w90%');
31+
32+
&.full {
33+
@include size('w100%');
34+
}
35+
}
36+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export type DeviceMockupProps = {
2+
type?: 'desktop' | null
3+
url?: string
4+
showButtons?: boolean
5+
closeButtonColor?: string
6+
maximizeButtonColor?: string
7+
minimizeButtonColor?: string
8+
className?: string
9+
}
10+
11+
export type ReactDeviceMockupProps = {
12+
children: React.ReactNode
13+
} & DeviceMockupProps

src/pages/blocks/device-mockup.astro

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
import { AspectRatio, Icon } from 'webcoreui/astro'
3+
4+
import Layout from '@static/Layout.astro'
5+
6+
import AstroDeviceMockup from '@blocks/DeviceMockup/DeviceMockup.astro'
7+
import SvelteDeviceMockup from '@blocks/DeviceMockup/DeviceMockup.svelte'
8+
import ReactDeviceMockup from '@blocks/DeviceMockup/DeviceMockup.tsx'
9+
10+
import { getSections } from '@helpers'
11+
12+
const sections = getSections({
13+
title: '',
14+
components: [AstroDeviceMockup, SvelteDeviceMockup, ReactDeviceMockup]
15+
})
16+
---
17+
18+
<Layout>
19+
<h1>Device Mockup Blocks</h1>
20+
<h2>
21+
<a href="/blocks">
22+
{'<-'} Back to all blocks
23+
</a>
24+
</h2>
25+
26+
{sections.map(section => (
27+
<h3>{section.title} Blocks</h3>
28+
<div class="grid">
29+
<div class="mobile-container">
30+
<section.component className="example">
31+
<div class="grid sm">
32+
<AspectRatio ratio="1/1.5">
33+
<img
34+
src="/img/placeholder1.png"
35+
width="380"
36+
height="380"
37+
/>
38+
</AspectRatio>
39+
<Icon type="components" />
40+
<span class="muted">Mobile Mockup</span>
41+
</div>
42+
</section.component>
43+
</div>
44+
45+
<div class="grid md-2">
46+
<section.component type="desktop" className="example">
47+
<div class="grid sm">
48+
<AspectRatio ratio="21:9">
49+
<img
50+
src="/img/placeholder3.png"
51+
width="500"
52+
height="500"
53+
/>
54+
</AspectRatio>
55+
<span class="muted">Desktop Mockup</span>
56+
</div>
57+
</section.component>
58+
59+
<section.component
60+
type="desktop"
61+
url="webcoreui.dev"
62+
className="example"
63+
>
64+
<div class="grid sm">
65+
<AspectRatio ratio="21:9">
66+
<img
67+
src="/img/placeholder3.png"
68+
width="500"
69+
height="500"
70+
/>
71+
</AspectRatio>
72+
<span class="muted">Desktop Mockup with URL</span>
73+
</div>
74+
</section.component>
75+
76+
<section.component
77+
type="desktop"
78+
url="webcoreui.dev"
79+
showButtons={false}
80+
className="example"
81+
>
82+
<div class="grid sm">
83+
<AspectRatio ratio="21:9">
84+
<img
85+
src="/img/placeholder3.png"
86+
width="500"
87+
height="500"
88+
/>
89+
</AspectRatio>
90+
<span class="muted">Desktop Mockup without icons</span>
91+
</div>
92+
</section.component>
93+
94+
<section.component
95+
type="desktop"
96+
url="webcoreui.dev"
97+
className="example"
98+
closeButtonColor="#D13824"
99+
maximizeButtonColor="#E7A121"
100+
minimizeButtonColor="#97E038"
101+
>
102+
<div class="grid sm">
103+
<AspectRatio ratio="21:9">
104+
<img
105+
src="/img/placeholder3.png"
106+
width="500"
107+
height="500"
108+
/>
109+
</AspectRatio>
110+
<span class="muted">Desktop Mockup with icon colors</span>
111+
</div>
112+
</section.component>
113+
</div>
114+
</div>
115+
))}
116+
</Layout>
117+
118+
<style lang="scss" is:global>
119+
@use 'webcoreui/config' as *;
120+
121+
svg {
122+
@include spacing(none-auto);
123+
}
124+
125+
.example {
126+
@include typography(center);
127+
@include background(primary-50);
128+
}
129+
130+
.mobile-container {
131+
@include spacing(auto-none);
132+
133+
max-width: 300px;
134+
}
135+
136+
// .toggle {
137+
// @include typography(md);
138+
// @include spacing(py-xs, px-sm);
139+
// }
140+
</style>

src/pages/blocks/index.astro

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
---
2-
import { Card, Switch } from 'webcoreui/astro'
2+
import { AspectRatio, Card, Switch } from 'webcoreui/astro'
33
44
import Layout from '@static/Layout.astro'
55
import Link from '@static/Link.astro'
66
77
import BlogCard from '@blocks/BlogCard/BlogCard.astro'
88
import ComponentMap from '@blocks/ComponentMap/ComponentMap.astro'
9+
import DeviceMockup from '@blocks/DeviceMockup/DeviceMockup.astro'
910
import ErrorPage from '@blocks/ErrorPage/ErrorPage.astro'
1011
import FAQ from '@blocks/FAQ/FAQ.astro'
1112
import GridWithIcons from '@blocks/GridWithIcons/GridWithIcons.astro'
@@ -122,6 +123,20 @@ import User from '@blocks/User/User.astro'
122123
title="Blog Card Title"
123124
text="This is a blog card with an introductory test. Click me to navigate to more examples."
124125
/>
126+
127+
<DeviceMockup className="device-mockup-example">
128+
<div class="grid xs">
129+
<AspectRatio ratio="1">
130+
<img
131+
src="/img/placeholder1.png"
132+
width="380"
133+
height="380"
134+
/>
135+
</AspectRatio>
136+
<span class="muted">Device Mockup</span>
137+
<a href="/blocks/device-mockup">See examples {'->'}</a>
138+
</div>
139+
</DeviceMockup>
125140
</div>
126141
<div class="block-column flex column">
127142
<Card title="Tiles with Icons">
@@ -170,4 +185,9 @@ import User from '@blocks/User/User.astro'
170185
.block-column {
171186
@include size(w370px);
172187
}
188+
189+
.device-mockup-example {
190+
@include typography(center);
191+
@include background(primary-50);
192+
}
173193
</style>

0 commit comments

Comments
 (0)