Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
599df082
Commit
599df082
authored
Mar 19, 2021
by
Lyza Danger Gardner
Committed by
Lyza Gardner
Mar 23, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update playground app
Add some pattern structure to the playground app and a placeholder "Menu" demo
parent
d7a2a4e8
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
420 additions
and
28 deletions
+420
-28
ui-playground.mustache
dev-server/templates/ui-playground.mustache
+0
-1
PatternPage.js
dev-server/ui-playground/components/PatternPage.js
+140
-0
PlaygroundApp.js
dev-server/ui-playground/components/PlaygroundApp.js
+69
-0
MenuPatterns.js
dev-server/ui-playground/components/patterns/MenuPatterns.js
+29
-0
index.js
dev-server/ui-playground/index.js
+1
-1
jsx-to-string.js
dev-server/ui-playground/util/jsx-to-string.js
+50
-0
ui-playground.scss
src/styles/ui-playground/ui-playground.scss
+131
-26
No files found.
dev-server/templates/ui-playground.mustache
View file @
599df082
...
...
@@ -4,7 +4,6 @@
<meta
charset=
"UTF-8"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1"
>
<title>
UI component playground
</title>
<link
rel=
"stylesheet"
href=
"
{{
resourceRoot
}}
/styles/sidebar.css"
>
<link
rel=
"stylesheet"
href=
"
{{
resourceRoot
}}
/styles/ui-playground.css"
>
</head>
<body>
...
...
dev-server/ui-playground/components/PatternPage.js
0 → 100644
View file @
599df082
import
{
toChildArray
}
from
'preact'
;
import
{
jsxToString
}
from
'../util/jsx-to-string'
;
/**
* Components to render patterns and examples. Typical structure of a "Demo"
* page might be:
*
* <PatternPage title="Zoo Animals">
* <Pattern title="Elephant">
* <p>Everyone loves an elephant.</p>
*
* <PatternExamples title="Colored elephants">
* <PatternExample details="Pink elephant">
* <Elephant color="pink" />
* </PatternExample>
* <PatternExample details="Blue elephant">
* <Elephant color="blue" />
* </PatternExample>
* </PatternExamples>
*
* <PatternExamples title="Patterned elephants">
* <PatternExample details="Spotted elephant">
* <Elephant variant="spotted" />
* </PatternExample>
* </PatternExamples>
* </Pattern>
*
* <Pattern title="Monkeys">
* <PatternExamples>
* <PatternExample details="Your basic monkey">
* <Monkey />
* </PatternExample>
* </PatternExamples>
* </Pattern>
* </PatternPage>
*/
/**
* @typedef PatternPageProps
* @prop {import("preact").ComponentChildren} children
* @prop {string} title
*/
/**
* Render a page of patterns
* @param {PatternPageProps} props
*/
export
function
PatternPage
({
children
,
title
})
{
return
(
<
section
className
=
"PatternPage"
>
<
h1
>
{
title
}
<
/h1
>
<
div
className
=
"PatternPage__content"
>
{
children
}
<
/div
>
<
/section
>
);
}
/**
* @typedef PatternProps
* @prop {import("preact").ComponentChildren} children
* @prop {string} title
*/
/**
* A pattern and its examples
* @param {PatternProps} props
*/
export
function
Pattern
({
children
,
title
})
{
return
(
<
section
className
=
"Pattern"
>
<
h2
>
{
title
}
<
/h2
>
{
children
}
<
/section
>
);
}
/**
* @typedef PatternExamplesProps
* @prop {import("preact").ComponentChildren} children
* @prop {string} [title]
*/
/**
* Tabular layout of one or more `PatternExample` components, with optional
* title.
*
* @param {PatternExamplesProps} props
*/
export
function
PatternExamples
({
children
,
title
})
{
return
(
<
table
className
=
"PatternExamples"
>
{
title
&&
(
<
tr
>
<
th
colSpan
=
"3"
>
<
h3
>
{
title
}
<
/h3
>
<
/th
>
<
/tr
>
)}
<
tr
>
<
th
>
Example
<
/th
>
<
th
>
Details
<
/th
>
<
th
>
Source
<
/th
>
<
/tr
>
{
children
}
<
/table
>
);
}
/**
* @typedef PatternExampleProps
* @prop {import("preact").ComponentChildren} children - Example source
* @prop {string} details - Details about the pattern example
*/
/**
* Tabular layout of a single example. Will render its `children` as the
* example, as well as the source JSX of its `children`
*
* @param {PatternExampleProps} props
*/
export
function
PatternExample
({
children
,
details
})
{
const
source
=
toChildArray
(
children
).
map
((
child
,
idx
)
=>
{
return
(
<
li
key
=
{
idx
}
>
<
code
>
<
pre
>
{
jsxToString
(
child
)}
<
/pre
>
<
/code
>
<
/li
>
);
});
return
(
<
tr
>
<
td
className
=
"PatternExample__example"
>
{
children
}
<
/td
>
<
td
>
{
details
}
<
/td
>
<
td
>
<
ul
>
{
source
}
<
/ul
>
<
/td
>
<
/tr
>
);
}
dev-server/ui-playground/PlaygroundApp.js
→
dev-server/ui-playground/
components/
PlaygroundApp.js
View file @
599df082
import
{
SvgIcon
}
from
'@hypothesis/frontend-shared'
;
import
Button
from
'../../src/sidebar/components/Button'
;
import
Menu
from
'../../src/sidebar/components/Menu'
;
import
MenuItem
from
'../../src/sidebar/components/MenuItem'
;
import
MenuPatterns
from
'./patterns/MenuPatterns'
;
import
{
useRoute
}
from
'./router'
;
function
ComponentDemo
({
title
,
children
})
{
return
(
<
section
>
<
h1
className
=
"heading"
>
{
title
}
<
/h1
>
{
children
}
<
/section
>
);
}
function
ButtonDemo
()
{
return
(
<
ComponentDemo
title
=
"Button"
>
<
Button
buttonText
=
"Text button"
/>
<
Button
icon
=
"edit"
title
=
"Icon button"
/>
<
Button
icon
=
"trash"
buttonText
=
"Icon + text button"
/>
<
Button
disabled
=
{
true
}
buttonText
=
"Disabled button"
/>
<
/ComponentDemo
>
);
}
function
MenuDemo
()
{
return
(
<
ComponentDemo
title
=
"Menu"
>
<
Menu
label
=
"Edit"
>
<
MenuItem
label
=
"Zoom in"
/>
<
MenuItem
label
=
"Zoom out"
/>
<
MenuItem
label
=
"Undo"
/>
<
MenuItem
label
=
"Redo"
/>
<
/Menu
>
<
/ComponentDemo
>
);
}
import
{
useRoute
}
from
'../router'
;
function
HomeRoute
()
{
return
(
...
...
@@ -54,15 +19,10 @@ const routes = [
title
:
'Home'
,
component
:
HomeRoute
,
},
{
route
:
'/button'
,
title
:
'Button'
,
component
:
ButtonDemo
,
},
{
route
:
'/menu'
,
title
:
'Menu'
,
component
:
Menu
Demo
,
component
:
Menu
Patterns
,
},
];
...
...
@@ -83,23 +43,25 @@ export default function PlaygroundApp() {
return
(
<
main
className
=
"PlaygroundApp"
>
<
div
className
=
"PlaygroundApp__sidebar"
>
<
a
className
=
"PlaygroundApp__nav-link u-center"
href
=
{
baseUrl
}
onClick
=
{
e
=>
navigate
(
e
,
'/'
)}
>
<
SvgIcon
name
=
"logo"
/>
<
/a
>
{
demoRoutes
.
map
(
c
=>
(
<
a
className
=
"PlaygroundApp__nav-link"
key
=
{
c
.
route
}
href
=
{
c
.
route
}
onClick
=
{
e
=>
navigate
(
e
,
c
.
route
)}
>
{
c
.
title
}
<
div
className
=
"PlaygroundApp__sidebar-home"
>
<
a
href
=
{
baseUrl
}
onClick
=
{
e
=>
navigate
(
e
,
'/'
)}
>
<
SvgIcon
name
=
"logo"
/>
<
/a
>
))}
<
/div
>
<
ul
>
{
demoRoutes
.
map
(
c
=>
(
<
li
key
=
{
c
.
route
}
>
<
a
className
=
"PlaygroundApp__nav-link"
key
=
{
c
.
route
}
href
=
{
c
.
route
}
onClick
=
{
e
=>
navigate
(
e
,
c
.
route
)}
>
{
c
.
title
}
<
/a
>
<
/li
>
))}
<
/ul
>
<
/div
>
<
div
className
=
"PlaygroundApp__content"
>
{
content
}
<
/div
>
<
/main
>
...
...
dev-server/ui-playground/components/patterns/MenuPatterns.js
0 → 100644
View file @
599df082
import
{
PatternPage
,
Pattern
,
PatternExamples
,
PatternExample
,
}
from
'../PatternPage'
;
import
Menu
from
'../../../../src/sidebar/components/Menu'
;
import
MenuItem
from
'../../../../src/sidebar/components/MenuItem'
;
export
default
function
MenuPatterns
()
{
return
(
<
PatternPage
title
=
"Menu"
>
<
Pattern
title
=
"Menu"
>
<
p
>
A
simple
Menu
usage
example
<
/p
>
<
PatternExamples
>
<
PatternExample
details
=
"Menu"
>
<
Menu
label
=
"Edit"
>
<
MenuItem
label
=
"Zoom in"
/>
<
MenuItem
label
=
"Zoom out"
/>
<
MenuItem
label
=
"Undo"
/>
<
MenuItem
label
=
"Redo"
/>
<
/Menu
>
<
/PatternExample
>
<
/PatternExamples
>
<
/Pattern
>
<
/PatternPage
>
);
}
dev-server/ui-playground/index.js
View file @
599df082
import
{
registerIcons
}
from
'@hypothesis/frontend-shared'
;
import
{
render
}
from
'preact'
;
import
PlaygroundApp
from
'./PlaygroundApp'
;
import
PlaygroundApp
from
'./
components/
PlaygroundApp'
;
import
sidebarIcons
from
'../../src/sidebar/icons'
;
registerIcons
(
sidebarIcons
);
...
...
dev-server/ui-playground/util/jsx-to-string.js
0 → 100644
View file @
599df082
function
escapeQuotes
(
str
)
{
return
str
.
replace
(
/"/g
,
'
\\
"'
);
}
function
componentName
(
type
)
{
if
(
typeof
type
===
'string'
)
{
return
type
;
}
else
{
return
type
.
displayName
||
type
.
name
;
}
}
export
function
jsxToString
(
vnode
)
{
if
(
typeof
vnode
===
'string'
||
typeof
vnode
===
'number'
)
{
return
vnode
.
toString
();
}
else
if
(
vnode
?.
type
)
{
const
name
=
componentName
(
vnode
.
type
);
// TODO - Add in the `key` prop which is extracted off the props into `vnode.key`.
let
propStr
=
Object
.
entries
(
vnode
.
props
)
.
map
(([
name
,
value
])
=>
{
if
(
name
===
'children'
)
{
return
''
;
}
// nb. We assume that `value` is something that can easily be stringified
// using `String(value)`.
return
`
${
name
}
="
${
escapeQuotes
(
String
(
value
))}
"`
;
})
.
join
(
' '
)
.
trim
();
if
(
propStr
.
length
>
0
)
{
propStr
=
' '
+
propStr
;
}
const
children
=
vnode
.
props
.
children
;
if
(
children
)
{
// TODO - Be smart about splitting children over multiple lines
// and indentation
const
childrenStr
=
Array
.
isArray
(
children
)
?
children
.
map
(
jsxToString
).
join
(
'
\
n'
)
:
jsxToString
(
children
);
return
`<
${
name
}${
propStr
}
>\n
${
childrenStr
}
\n</
${
name
}
>`
;
}
else
{
// No children - use a self-closing tag.
return
`<
${
name
}${
propStr
}
/>`
;
}
}
else
{
return
''
;
}
}
src/styles/ui-playground/ui-playground.scss
View file @
599df082
@use
'../reset'
;
@use
'../sidebar/elements'
;
@use
'../mixins/layout'
;
@use
'../variables'
as
var
;
@use
'../sidebar/components/Menu'
;
@use
'../sidebar/components/MenuItem'
;
$title-font
:
20pt
;
$background-color
:
#ededed
;
$background-color
:
#9b9595
;
body
{
font-size
:
100%
;
}
h1
{
font-size
:
1
.75em
;
font-weight
:
bold
;
}
h2
{
font-size
:
1
.5em
;
width
:
100%
;
border-left
:
6px
solid
var
.
$color-brand
;
font-weight
:
bold
;
padding-left
:
0
.5em
;
}
h3
{
width
:
100%
;
font-size
:
1
.125em
;
font-weight
:
normal
;
font-style
:
italic
;
}
pre
{
margin
:
0
;
}
// Utilities
.u-center
{
...
...
@@ -8,45 +44,114 @@ $background-color: #ededed;
// Component styles
.PlaygroundApp
{
display
:
flex
;
flex-direction
:
row
;
display
:
grid
;
grid-template-areas
:
'navigation'
'content'
;
max-width
:
600px
;
margin-left
:
auto
;
margin-right
:
auto
;
margin-top
:
10px
;
min-height
:
90vh
;
}
&
__content
{
padding
:
var
.
$layout-space
;
}
&
__sidebar
{
grid-area
:
'navigation'
;
max-height
:
20em
;
overflow
:
scroll
;
background-color
:
var
.
$grey-2
;
}
&
__sidebar-home
{
text-align
:
center
;
padding
:
var
.
$layout-space
;
}
.PlaygroundApp__sidebar
{
display
:
flex
;
flex-direction
:
column
;
padding
:
10px
;
background-color
:
$background-color
;
border-radius
:
3px
;
margin-right
:
10px
;
&
__content
{
grid-area
:
'content'
;
}
}
.PlaygroundApp__nav-link
{
padding
:
5px
;
font-size
:
12pt
;
width
:
100%
;
padding
:
var
.
$layout-space
;
font-size
:
var
.
$font-size--subheading
;
border-left
:
5px
solid
transparent
;
&
:hover
{
background-color
:
#ddd
;
background-color
:
var
.
$grey-3
;
border-left
:
5px
solid
var
.
$color-brand
;
}
}
.PlaygroundApp__content
{
flex-grow
:
1
;
// Temporarily enforce the body font size of the client to demonstrate how
// components would scale in-situ
.PatternPage
{
font-size
:
13px
;
&
__content
{
padding
:
2em
0
;
}
}
.heading
{
font-size
:
$title-font
;
border-bottom
:
2px
solid
$background-color
;
margin-bottom
:
20px
;
.Pattern
{
margin-bottom
:
4em
;
p
{
margin
:
1em
;
}
}
.PatternExamples
{
border
:
1px
solid
var
.
$grey-3
;
border-collapse
:
collapse
;
width
:
100%
;
margin-bottom
:
2em
;
th
,
td
{
padding
:
0
.5em
;
}
th
{
background-color
:
var
.
$grey-1
;
border-bottom
:
1px
solid
var
.
$grey-3
;
text-align
:
left
;
}
td
{
padding-top
:
10px
;
padding-bottom
:
10px
;
}
tr
:nth-child
(
even
)
td
{
background
:
var
.
$grey-0
;
}
code
{
color
:
var
.
$grey-mid
;
}
}
.PatternExample
{
&
__example
{
display
:
flex
;
align-items
:
center
;
&
>
*
+
*
{
margin-left
:
1em
;
}
}
}
// Element styles
body
{
font-family
:
sans-serif
;
}
@media
screen
and
(
min-width
:
60em
)
{
.PlaygroundApp
{
height
:
100vh
;
grid-template-columns
:
20em
auto
;
column-gap
:
1em
;
grid-template-areas
:
'navigation content'
;
&
__sidebar
{
max-height
:
none
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment