Group up existing components into elements

This commit is contained in:
Eduard Urbach 2019-11-19 16:12:52 +09:00
parent dc4fc1410d
commit c542bcdcd6
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
77 changed files with 291 additions and 349 deletions

View File

@ -13,22 +13,18 @@
"mixins/feature-card",
"mixins/horizontal-line",
"mixins/comments",
"mixins/input",
"reset",
"base",
"typography",
"mountable",
"layout",
"search",
"headers",
"input",
"grid",
"post",
"thread",
"tabs",
"tags",
"user",
"video",
"loading",
"fade",
"embedded"
],
@ -43,4 +39,4 @@
"http": 4000,
"https": 4001
}
}
}

15
elements/AMV/AMV.pixy Normal file
View File

@ -0,0 +1,15 @@
component AMV(amv *arn.AMV, user *arn.User)
.amv.mountable
AMVVideo(amv)
AMVFooter(amv, user)
component AMVFooter(amv *arn.AMV, user *arn.User)
footer.amv-footer
if amv.Title.ByUser(user) == ""
a(href=amv.Link() + "/edit") untitled
else
a(href=amv.Link())= amv.Title.ByUser(user)
span posted
span.utc-date.no-tip(data-date=amv.Created)
span by
a(href=amv.Creator().Link())= amv.Creator().Nick + " "

11
elements/AMV/AMVMini.pixy Normal file
View File

@ -0,0 +1,11 @@
component AMVMini(amv *arn.AMV, user *arn.User)
.amv.mountable
AMVVideo(amv)
AMVMiniFooter(amv, user)
component AMVMiniFooter(amv *arn.AMV, user *arn.User)
footer.amv-footer
if amv.Title.ByUser(user) == ""
a(href=amv.Link() + "/edit") untitled
else
a(href=amv.Link())= amv.Title.ByUser(user)

View File

@ -0,0 +1,9 @@
component AMVVideo(amv *arn.AMV)
.video-container(id=amv.ID, data-api="/api/amv/" + amv.ID)
video.video.lazy.action(data-action="toggleFullscreen", data-trigger="dblclick", data-id=amv.ID)
source(data-src=amv.VideoLink(), data-type="video/webm")
//- button.media-play-button
//- RawIcon("play")
VideoControls(amv.ID, amv.Info.Duration)

View File

@ -0,0 +1,7 @@
component AnimeList(animeListItems []*arn.AnimeListItem, nextIndex int, viewUser *arn.User, user *arn.User)
#load-more-target.anime-list
AnimeListScrollable(animeListItems, viewUser, user)
if nextIndex != -1
.buttons
LoadMore(nextIndex)

View File

@ -1,11 +1,3 @@
component AnimeList(animeListItems []*arn.AnimeListItem, nextIndex int, viewUser *arn.User, user *arn.User)
#load-more-target.anime-list
AnimeListScrollable(animeListItems, viewUser, user)
if nextIndex != -1
.buttons
LoadMore(nextIndex)
component AnimeListScrollable(animeListItems []*arn.AnimeListItem, viewUser *arn.User, user *arn.User)
each item in animeListItems
.anime-list-item.mountable(title=item.Notes, data-api="/api/animelist/" + viewUser.ID + "/field/Items[AnimeID=\"" + item.AnimeID + "\"]")

View File

@ -0,0 +1,2 @@
component Avatar(user *arn.User)
CustomAvatar(user, user.Link(), user.Nick)

View File

@ -0,0 +1,5 @@
component AvatarNoLink(user *arn.User)
if user.HasAvatar()
img.user-image.lazy(data-src=user.AvatarLink("small"), data-webp="true", alt=user.Nick)
else
SVGAvatar(user)

View File

@ -0,0 +1,3 @@
component AvatarNoTip(user *arn.User)
a.user(href=user.Link(), title=user.Nick)
AvatarNoLink(user)

View File

@ -0,0 +1,7 @@
component CustomAvatar(user *arn.User, link string, title string)
a.user.tip(href=link, aria-label=title)
AvatarNoLink(user)
if user.IsPro()
.user-pro-icon
RawIcon("star")

View File

@ -0,0 +1,5 @@
component ProfileImage(user *arn.User)
if user.HasAvatar()
img.profile-image.lazy(data-src=user.AvatarLink("large"), data-webp="true", alt="Profile image", importance="high")
else
SVGProfileImage(user)

View File

@ -0,0 +1,9 @@
component SVGAvatar(user *arn.User)
svg.user-image(viewBox="0 0 50 50")
circle.head(cx="25", cy="19", r="10")
circle.body(cx="25", cy="50", r="20")
if len(user.Nick) <= 6
text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick
else
text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick[:6]

View File

@ -0,0 +1,4 @@
component SVGProfileImage(user *arn.User)
svg.profile-image(viewBox="0 0 50 50", alt="Profile image")
circle.head(cx="25", cy="19", r="10")
circle.body(cx="25", cy="50", r="20")

View File

@ -0,0 +1,2 @@
component ExternalMedia(media *arn.ExternalMedia)
iframe.lazy(data-src=media.EmbedLink(), title=media.Service + " media", allowfullscreen)

2
elements/Icon/Icon.pixy Normal file
View File

@ -0,0 +1,2 @@
component Icon(name string)
svg-icon.padded-icon(name=name, class="icon-" + name)

View File

@ -0,0 +1,2 @@
component RawIcon(name string)
svg-icon(name=name, class="icon-" + name)

View File

@ -0,0 +1,11 @@
component InputBool(id string, value bool, label string, title string)
.widget-section
label= label + ":"
if value
button.action(id=id, data-action="disable", data-trigger="click", data-field=id, title=title)
Icon("toggle-on")
span ON
else
button.action(id=id, data-action="enable", data-trigger="click", data-field=id, title=title)
Icon("toggle-off")
span OFF

View File

@ -0,0 +1,9 @@
component InputColor(id string, variable string, label string)
.widget-section
label(for=id)= label
.color-picker-container
.widget-ui-element.color-picker.color-box.action(data-color="var(--" + variable + ")", data-variable=variable, data-action="pickColor", data-trigger="click")
button.tip(aria-label="Reset", disabled)
RawIcon("power-off")

View File

@ -0,0 +1,6 @@
component InputFileUpload(id string, label string, uploadType string, endpoint string)
.widget-section
label= label + ":"
button.action(id=id, data-action="selectFile", data-trigger="click", data-endpoint=endpoint, data-type=uploadType)
Icon("upload")
span Select file

View File

@ -0,0 +1,14 @@
component InputNumber(id string, value float64, label string, placeholder string, min string, max string, step string)
.widget-section
label(for=id)= label + ":"
input.widget-ui-element.action(id=id, data-field=id, type="number", value=value, min=min, max=max, step=step, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
component InputNumberWithButtons(id string, value float64, label string, placeholder string, min string, max string, step string)
.widget-section
label(for=id)= label + ":"
.number-input-container
input.widget-ui-element.action(id=id, data-field=id, type="number", value=value, min=min, max=max, step=step, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
button.action.tip(data-action="addNumber", data-trigger="click", data-id=id, data-add="1", aria-label="Increase by 1")
RawIcon("plus")
button.action.tip(data-action="addNumber", data-trigger="click", data-id=id, data-add="-1", aria-label="Decrease by 1")
RawIcon("minus")

View File

@ -0,0 +1,6 @@
component InputSelection(id string, value string, label string, placeholder string, options []*arn.Option)
.widget-section
label(for=id)= label + ":"
select.widget-ui-element.action(id=id, data-field=id, value=value, title=placeholder, data-action="save", data-trigger="change")
each option in options
option(value=option.Value)= option.Label

View File

@ -0,0 +1,13 @@
component InputTags(id string, value []string, label string, tooltip string)
.widget-section
label(for=id)= label + ":"
.tags(id=id)
for index, tag := range value
.tag.tag-edit.action(contenteditable="true", data-action="save", data-trigger="focusout", data-field=id + "[" + strconv.Itoa(index) + "]")= tag
button.tag-remove.action(data-action="arrayRemove", data-trigger="click", data-field=id, data-index=index)
RawIcon("trash")
button.tag-add.action(data-action="arrayAppend", data-trigger="click", data-field=id, title="Add more")
RawIcon("plus")
p!= tooltip

View File

@ -0,0 +1,4 @@
component InputText(id string, value string, label string, placeholder string, maxLength int)
.widget-section
label(for=id)= label + ":"
input.widget-ui-element.action(id=id, data-field=id, type="text", value=value, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength)

View File

@ -0,0 +1,4 @@
component InputTextArea(id string, value string, label string, placeholder string, maxLength int)
.widget-section
label(for=id)= label + ":"
textarea.widget-ui-element.action(id=id, data-field=id, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength)= value

View File

@ -1,19 +1,3 @@
mixin input-focus
:focus
border 1px solid input-focus-border-color !important
// TODO: Replace with alpha(main-color, 20%) function
box-shadow 0 0 6px rgba(248, 165, 130, 0.2) !important
mixin button-hover
:hover,
&.active
cursor pointer
color button-hover-color
background button-hover-background
:active
transform translateY(3px)
input, textarea, button, .button, select
ui-element
font-family inherit
@ -100,4 +84,4 @@ textarea
justify-content center
margin-left 0.2rem
width input-height
height input-height
height input-height

14
elements/Quote/Quote.pixy Normal file
View File

@ -0,0 +1,14 @@
component Quote(quote *arn.Quote, user *arn.User)
.quote.mountable
QuoteContent(quote, user)
QuoteFooter(quote)
component QuoteContent(quote *arn.Quote, user *arn.User)
.quote-content
a.quotation(href=quote.Link())
QuoteText(quote)
QuoteCharacter(quote, user)
component QuoteText(quote *arn.Quote)
blockquote!= utils.RenderQuoteText(quote.Text.English)

View File

@ -0,0 +1,56 @@
const quote-margin = 1rem
.quote
vertical
flex 1
flex-basis 500px
margin quote-margin 0
> 500px
.quote
margin quote-margin
.quote-content
vertical
ui-element
border-left 5px solid quote-side-border-color !important
box-shadow shadow-light
.quote-line
// ...
.quote-character
horizontal
align-self flex-end
margin 0 1em 1em 0
.character
margin 0
.quote-footer
media-footer
blockquote
flex-grow 1
padding 1em
p
line-height 2em
quotes "\201C""\201D"
color text-color
:before
color quote-color
content open-quote
font-size 4em
line-height 0.1em
margin-right 0.25em
vertical-align -0.4em
:after
color quote-color
content close-quote
font-size 4em
line-height 0.1em
margin-left 0.25em
vertical-align -0.4em

View File

@ -0,0 +1,4 @@
component QuoteCharacter(quote *arn.Quote, user *arn.User)
if quote.CharacterID != "" && quote.Character() != nil
footer.quote-character
CharacterSmall(quote.Character(), user)

View File

@ -0,0 +1,6 @@
component QuoteFooter(quote *arn.Quote)
footer.quote-footer
span posted
span.utc-date.no-tip(data-date=quote.Created)
span by
a(href=quote.Creator().Link())= quote.Creator().Nick

View File

@ -0,0 +1,14 @@
component QuotePreview(quote *arn.Quote, user *arn.User)
.quote.mountable
QuoteContentPreview(quote, user)
QuoteFooter(quote)
component QuoteContentPreview(quote *arn.Quote, user *arn.User)
.quote-content
a.quotation(href=quote.Link())
QuoteTextPreview(quote)
QuoteCharacter(quote, user)
component QuoteTextPreview(quote *arn.Quote)
blockquote!= utils.RenderQuoteText(utils.CutLongDescription(quote.Text.English))

View File

@ -1,2 +1,2 @@
component FuzzySearch(value string)
component Search(value string)
input#search.action(data-action="search", data-trigger="input", type="search", autocomplete="off", autocorrect="off", autocapitalize="none", spellcheck="false", placeholder="Search...", title="Shortcut: F", maxlength="100", value=value)

View File

@ -3,11 +3,6 @@ component SoundTrack(track *arn.SoundTrack, user *arn.User)
SoundTrackContent(track, user)
SoundTrackFooter(track, user)
component SoundTrackMini(track *arn.SoundTrack, user *arn.User)
.soundtrack.mountable(id=track.ID)
SoundTrackContent(track, user)
SoundTrackMiniFooter(track, user)
component SoundTrackContent(track *arn.SoundTrack, user *arn.User)
.soundtrack-content
if track.MainAnime() != nil
@ -42,13 +37,3 @@ component SoundTrackFooter(track *arn.SoundTrack, user *arn.User)
span.utc-date.no-tip(data-date=track.Created)
span by
a(href=track.Creator().Link())= track.Creator().Nick + " "
component SoundTrackMiniFooter(track *arn.SoundTrack, user *arn.User)
footer.soundtrack-footer
if track.Title.ByUser(user) == ""
a(href=track.Link() + "/edit") untitled
else
a(href=track.Link())= track.Title.ByUser(user)
component ExternalMedia(media *arn.ExternalMedia)
iframe.lazy(data-src=media.EmbedLink(), title=media.Service + " media", allowfullscreen)

View File

@ -0,0 +1,11 @@
component SoundTrackMini(track *arn.SoundTrack, user *arn.User)
.soundtrack.mountable(id=track.ID)
SoundTrackContent(track, user)
SoundTrackMiniFooter(track, user)
component SoundTrackMiniFooter(track *arn.SoundTrack, user *arn.User)
footer.soundtrack-footer
if track.Title.ByUser(user) == ""
a(href=track.Link() + "/edit") untitled
else
a(href=track.Link())= track.Title.ByUser(user)

View File

@ -30,4 +30,4 @@
.info-message
color white
background tab-active-background
background tab-active-background

4
elements/Tab/Tab.pixy Normal file
View File

@ -0,0 +1,4 @@
component Tab(label string, icon string, url string)
a.tab.action(href=url, data-action="diff", data-trigger="click", aria-label=label, dropzone="move")
Icon(icon)
span.tab-text= label

View File

@ -1,8 +1,3 @@
component Tab(label string, icon string, url string)
a.tab.action(href=url, data-action="diff", data-trigger="click", aria-label=label, dropzone="move")
Icon(icon)
span.tab-text= label
component TabWithCount(label string, count int, icon string, url string)
a.tab.action(href=url, data-action="diff", data-trigger="click", aria-label=label, dropzone="move")
Icon(icon)

View File

@ -1,37 +0,0 @@
component AMV(amv *arn.AMV, user *arn.User)
.amv.mountable
AMVVideo(amv)
AMVFooter(amv, user)
component AMVMini(amv *arn.AMV, user *arn.User)
.amv.mountable
AMVVideo(amv)
AMVMiniFooter(amv, user)
component AMVVideo(amv *arn.AMV)
.video-container(id=amv.ID, data-api="/api/amv/" + amv.ID)
video.video.lazy.action(data-action="toggleFullscreen", data-trigger="dblclick", data-id=amv.ID)
source(data-src=amv.VideoLink(), data-type="video/webm")
//- button.media-play-button
//- RawIcon("play")
VideoControls(amv.ID, amv.Info.Duration)
component AMVFooter(amv *arn.AMV, user *arn.User)
footer.amv-footer
if amv.Title.ByUser(user) == ""
a(href=amv.Link() + "/edit") untitled
else
a(href=amv.Link())= amv.Title.ByUser(user)
span posted
span.utc-date.no-tip(data-date=amv.Created)
span by
a(href=amv.Creator().Link())= amv.Creator().Nick + " "
component AMVMiniFooter(amv *arn.AMV, user *arn.User)
footer.amv-footer
if amv.Title.ByUser(user) == ""
a(href=amv.Link() + "/edit") untitled
else
a(href=amv.Link())= amv.Title.ByUser(user)

View File

@ -1,41 +0,0 @@
component Avatar(user *arn.User)
CustomAvatar(user, user.Link(), user.Nick)
component CustomAvatar(user *arn.User, link string, title string)
a.user.tip(href=link, aria-label=title)
AvatarNoLink(user)
if user.IsPro()
.user-pro-icon
RawIcon("star")
component AvatarNoLink(user *arn.User)
if user.HasAvatar()
img.user-image.lazy(data-src=user.AvatarLink("small"), data-webp="true", alt=user.Nick)
else
SVGAvatar(user)
component AvatarNoTip(user *arn.User)
a.user(href=user.Link(), title=user.Nick)
AvatarNoLink(user)
component ProfileImage(user *arn.User)
if user.HasAvatar()
img.profile-image.lazy(data-src=user.AvatarLink("large"), data-webp="true", alt="Profile image", importance="high")
else
SVGProfileImage(user)
component SVGAvatar(user *arn.User)
svg.user-image(viewBox="0 0 50 50")
circle.head(cx="25", cy="19", r="10")
circle.body(cx="25", cy="50", r="20")
if len(user.Nick) <= 6
text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick
else
text.svg-nick(x="25", y="44", text-anchor="middle")= user.Nick[:6]
component SVGProfileImage(user *arn.User)
svg.profile-image(viewBox="0 0 50 50", alt="Profile image")
circle.head(cx="25", cy="19", r="10")
circle.body(cx="25", cy="50", r="20")

View File

@ -1,5 +0,0 @@
component Icon(name string)
svg-icon.padded-icon(name=name, class="icon-" + name)
component RawIcon(name string)
svg-icon(name=name, class="icon-" + name)

View File

@ -1,75 +0,0 @@
component InputText(id string, value string, label string, placeholder string, maxLength int)
.widget-section
label(for=id)= label + ":"
input.widget-ui-element.action(id=id, data-field=id, type="text", value=value, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength)
component InputBool(id string, value bool, label string, title string)
.widget-section
label= label + ":"
if value
button.action(id=id, data-action="disable", data-trigger="click", data-field=id, title=title)
Icon("toggle-on")
span ON
else
button.action(id=id, data-action="enable", data-trigger="click", data-field=id, title=title)
Icon("toggle-off")
span OFF
//- input.widget-ui-element.action(id=id, data-field=id, type="checkbox", value=value, checked=value, data-action="save", data-trigger="change")
component InputTextArea(id string, value string, label string, placeholder string, maxLength int)
.widget-section
label(for=id)= label + ":"
textarea.widget-ui-element.action(id=id, data-field=id, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change", maxlength=maxLength)= value
component InputNumber(id string, value float64, label string, placeholder string, min string, max string, step string)
.widget-section
label(for=id)= label + ":"
input.widget-ui-element.action(id=id, data-field=id, type="number", value=value, min=min, max=max, step=step, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
component InputNumberWithButtons(id string, value float64, label string, placeholder string, min string, max string, step string)
.widget-section
label(for=id)= label + ":"
.number-input-container
input.widget-ui-element.action(id=id, data-field=id, type="number", value=value, min=min, max=max, step=step, placeholder=placeholder, title=placeholder, data-action="save", data-trigger="change")
button.action.tip(data-action="addNumber", data-trigger="click", data-id=id, data-add="1", aria-label="Increase by 1")
RawIcon("plus")
button.action.tip(data-action="addNumber", data-trigger="click", data-id=id, data-add="-1", aria-label="Decrease by 1")
RawIcon("minus")
component InputSelection(id string, value string, label string, placeholder string, options []*arn.Option)
.widget-section
label(for=id)= label + ":"
select.widget-ui-element.action(id=id, data-field=id, value=value, title=placeholder, data-action="save", data-trigger="change")
each option in options
option(value=option.Value)= option.Label
component InputFileUpload(id string, label string, uploadType string, endpoint string)
.widget-section
label= label + ":"
button.action(id=id, data-action="selectFile", data-trigger="click", data-endpoint=endpoint, data-type=uploadType)
Icon("upload")
span Select file
component InputTags(id string, value []string, label string, tooltip string)
.widget-section
label(for=id)= label + ":"
.tags(id=id)
for index, tag := range value
.tag.tag-edit.action(contenteditable="true", data-action="save", data-trigger="focusout", data-field=id + "[" + strconv.Itoa(index) + "]")= tag
button.tag-remove.action(data-action="arrayRemove", data-trigger="click", data-field=id, data-index=index)
RawIcon("trash")
button.tag-add.action(data-action="arrayAppend", data-trigger="click", data-field=id, title="Add more")
RawIcon("plus")
p!= tooltip
component InputColor(id string, variable string, label string)
.widget-section
label(for=id)= label
.color-picker-container
.widget-ui-element.color-picker.color-box.action(data-color="var(--" + variable + ")", data-variable=variable, data-action="pickColor", data-trigger="click")
button.tip(aria-label="Reset", disabled)
RawIcon("power-off")

View File

@ -1,41 +0,0 @@
component Quote(quote *arn.Quote, user *arn.User)
.quote.mountable
QuoteContent(quote, user)
QuoteFooter(quote)
component QuotePreview(quote *arn.Quote, user *arn.User)
.quote.mountable
QuoteContentPreview(quote, user)
QuoteFooter(quote)
component QuoteContent(quote *arn.Quote, user *arn.User)
.quote-content
a.quotation(href=quote.Link())
QuoteText(quote)
QuoteCharacter(quote, user)
component QuoteContentPreview(quote *arn.Quote, user *arn.User)
.quote-content
a.quotation(href=quote.Link())
QuoteTextPreview(quote)
QuoteCharacter(quote, user)
component QuoteText(quote *arn.Quote)
blockquote!= utils.RenderQuoteText(quote.Text.English)
component QuoteCharacter(quote *arn.Quote, user *arn.User)
if quote.CharacterID != "" && quote.Character() != nil
footer.quote-character
CharacterSmall(quote.Character(), user)
component QuoteTextPreview(quote *arn.Quote)
blockquote!= utils.RenderQuoteText(utils.CutLongDescription(quote.Text.English))
component QuoteFooter(quote *arn.Quote)
footer.quote-footer
span posted
span.utc-date.no-tip(data-date=quote.Created)
span by
a(href=quote.Creator().Link())= quote.Creator().Nick

View File

@ -94,17 +94,17 @@
:focus
transform scale(1.5)
.anime-list-item-actions
display none
// .anime-list-item-actions
// display none
> 740px
.anime-list-item-actions
display flex
flex-basis 30px
flex-shrink 1
// > 740px
// .anime-list-item-actions
// display flex
// flex-basis 30px
// flex-shrink 1
:empty
display none
// :empty
// display none
.anime-list-item-airing-date
display none
@ -123,4 +123,4 @@
< 1100px
.anime-list-item-rating-container
display none
display none

View File

@ -43,23 +43,6 @@
list-style-type none
margin 0
.character-anime
horizontal-wrap
.character-anime-item
horizontal
width 100%
max-width 440px
.character-anime-item-overview
anime-mini-item
.character-anime-item-image
anime-mini-item-image
.character-anime-item-details
margin-left 1rem
.character-spoiler
margin typography-margin 0

View File

@ -1,10 +1,6 @@
const group-padding-y = 0.75rem
const group-padding-x = 0.75rem
.groups-beta-message
text-align center
margin-bottom 1rem
.groups
display grid
grid-gap content-padding-half
@ -47,4 +43,4 @@ const group-padding-x = 0.75rem
right 1rem
text-align right
font-size 0.8rem
opacity 0.5
opacity 0.5

View File

@ -121,13 +121,6 @@ const profile-image-size = 280px
display grid
grid-template-columns 27% 46% 27%
.profile-pro-status
position absolute
right 0
bottom 0
padding content-padding
margin-top 0
.profile-introduction
h1, h2, h3, h4, h5, h6
text-align left
@ -241,4 +234,4 @@ const box-margin = 2px
.no-data
width 100%
text-align center
text-align center

View File

@ -1,60 +1,3 @@
const quote-margin = 1rem
.quotes
horizontal-wrap
justify-content space-around
.quote
vertical
flex 1
flex-basis 500px
margin quote-margin 0
> 500px
.quote
margin quote-margin
.quote-content
vertical
ui-element
border-left 5px solid quote-side-border-color !important
box-shadow shadow-light
.quote-line
// ...
.quote-character
horizontal
align-self flex-end
margin 0 1em 1em 0
.character
margin 0
.quote-footer
media-footer
blockquote
flex-grow 1
padding 1em
p
line-height 2em
quotes "\201C""\201D"
color text-color
:before
color quote-color
content open-quote
font-size 4em
line-height 0.1em
margin-right 0.25em
vertical-align -0.4em
:after
color quote-color
content close-quote
font-size 4em
line-height 0.1em
margin-left 0.25em
vertical-align -0.4em

View File

@ -0,0 +1,15 @@
mixin input-focus
:focus
border 1px solid input-focus-border-color !important
// TODO: Replace with alpha(main-color, 20%) function
box-shadow 0 0 6px rgba(248, 165, 130, 0.2) !important
mixin button-hover
:hover,
&.active
cursor pointer
color button-hover-color
background button-hover-background
:active
transform translateY(3px)