Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend a component #38

Closed
GesJeremie opened this issue Apr 1, 2015 · 12 comments
Closed

Extend a component #38

GesJeremie opened this issue Apr 1, 2015 · 12 comments

Comments

@GesJeremie
Copy link

For my job, i'm creating some base components (button, well, form, etc ...) to have a fresh UI when I start a new project.

For sure I will edit some components to match with the current design of the application I will build.

So I wanted to know how to extend a component (clean way).

// button.sass
@include component(button)
  // ....
// app.sass

// Here I want to "hook", "extends" the component and add new classes
@ ????????

// I didn't try that but maybe it works ?
@include component(button)
  // My hooks here.
@emilniklas
Copy link

You could argue that inheritance is redundant since we have options. However I agree with you that this would be nice to have while trying to think CSS in terms of OOP.

In native Sass you can write

@extend .button;

which works as you'd expect.

Unfortunately it doesn't seem to work to pass function returns to the @extend directive, without escaping:

@function component($name) {
    @return #{'.#{$name}'};
}
@extend component(button); // DOES NOT WORK
@extend #{component(button)}; // DOES WORK

Moreover, one could consider maybe a second argument to the component mixin:

@include component(submit, button) {
    //
}

This would of course do the @extend #{$extend} behind the scenes.

Or maybe, if we are focusing on explicit, comfortable syntax, we could have an extends function, which just passes the parent component name to the said second argument:

@include component(submit, extends(button)) {
    //
}

I would love to see an intuitive way to do this while preserving the clear syntax of csstyle.

@geddski
Copy link
Owner

geddski commented Apr 3, 2015

Thanks @GesJeremie, this is a use case I hadn't thought of. Some good ideas there from @emilniklas. I especially like the explicit extends(parent) idea. Let me play around with a few ideas and get back to you. Happy to hear additional input as well.

@geddski
Copy link
Owner

geddski commented Apr 3, 2015

Here's one way we could accomplish this:

@mixin inherit($name){
  @extend .#{$name};
}
@include component(fancytweet){
  @include inherit(tweet);
  color: blue;
}

@emilniklas
Copy link

Hmm. I wonder what the most commonly used term for this is. I personally like extends more than inherits. But maybe if we're breaking it out from the component mixin, inherit is a more descriptive word.

Reading out "include" before whatever word we choose, for me, is relevant somehow. It seems "include extends" is just as weird as "include inherits". Another option might be "include parent". Hmm...

@GesJeremie
Copy link
Author

Maybe that ? (.sass) :

@include component(fancytweet)
  @include use(tweet)
  color: blue

or

@include component(fancytweet)
  @include base(tweet)
  color: blue

or

@include component(fancytweet)
  @include version(tweet)
  color: blue

or

@include component(fancytweet)
  @include _(tweet)
  color: blue

@emilniklas
Copy link

Once more we should be clear on when to use this instead of options. In @GesJeremie's example a fancy tweet should be .tweet.--fancy, right?

@GesJeremie
Copy link
Author

For me, that stuff is not an option, i don't know how we can do, but for example I finished a button component :

// ===========================================================
// Component Button (v.1.0)
// ===========================================================
//
// UI button component for csstyle.io
//
// Copyright (c) 2015 Ges Jeremie
// http://www.gesjeremie.fr/
// 

// ===========================================================
// Config
// ===========================================================
$csstyle-button-namespace: "button" !default
$csstyle-button-font-family:  "Helvetica Neue", Helvetica, Arial, sans-serif !default
$csstyle-button-font-weight: 300 !default
$csstyle-button-base-font-size: 15px !default
$csstyle-button-base-padding-top-bottom: 6px !default
$csstyle-button-base-padding-right-left: 12px !default



// ===========================================================
// Mixins
// ===========================================================
=csstyle-button-variant($background, $color, $border)
  background-color: $background
  color: $color
  border-color: $border

=csstyle-button-size($font-size, $padding-top-bottom, $padding-right-left)
  font-size: $font-size
  padding: $padding-top-bottom $padding-right-left

// ===========================================================
// Component
// ===========================================================
@include component($csstyle-button-namespace)

  // ===========================================================
  // Default part
  // ===========================================================
  font-family: $csstyle-button-font-family
  font-weight: $csstyle-button-font-weight
  cursor: pointer
  text-decoration: none !important
  -ms-touch-action: manipulation
  touch-action: manipulation
  cursor: pointer
  -webkit-user-select: none
  -moz-user-select: none
  -ms-user-select: none
  user-select: none
  border-radius: 5px
  border: 1px solid transparent
  +csstyle-button-variant(#d6e1e5, #5e696d, #d6e1e5)
  +csstyle-button-size($csstyle-button-base-font-size, $csstyle-button-base-padding-top-bottom, $csstyle-button-base-padding-right-left)

  &:hover,
  &:focus,
  &:active,
    outline: 0
    +csstyle-button-variant(#e1eef3, #5e696d, #e1eef3)


  // ===========================================================
  // Sizes
  // ===========================================================

  // extra small button
  @include option(xs)
    +csstyle-button-size($csstyle-button-base-font-size * 0.8, $csstyle-button-base-padding-top-bottom * 0.6, $csstyle-button-base-padding-right-left * 0.6)

  // small button
  @include option(sm)
    +csstyle-button-size($csstyle-button-base-font-size * 0.8, $csstyle-button-base-padding-top-bottom * 0.8, $csstyle-button-base-padding-right-left * 0.8)

  @include option(md)
    +csstyle-button-size($csstyle-button-base-font-size, $csstyle-button-base-padding-top-bottom, $csstyle-button-base-padding-right-left)

  // large button
  @include option(lg)
    +csstyle-button-size($csstyle-button-base-font-size * 1.2, $csstyle-button-base-padding-top-bottom * 1.2, $csstyle-button-base-padding-right-left * 1.2)

  // extra large button
  @include option(xl)
    +csstyle-button-size($csstyle-button-base-font-size * 1.4, $csstyle-button-base-padding-top-bottom * 1.6, $csstyle-button-base-padding-right-left * 1.6)

  // ===========================================================
  // Block
  // ===========================================================

  @include option(block)
    width: 100%
    display: inline-block

  // ===========================================================
  // Colors
  // ===========================================================

  // Default
  @include option(default)
    +csstyle-button-variant(#d6e1e5, #5e696d, #d6e1e5)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#e1eef3, #5e696d, #e1eef3)

  // Success
  @include option(success)
    +csstyle-button-variant(#3eb5ac, #fff, #3eb5ac)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#45c8be, #fff, #45c8be)

  // Primary
  @include option(primary)
    +csstyle-button-variant(#02baf2, #fff, #02baf2)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#0fc7ff, #fff, #0fc7ff)

  // Info
  @include option(info)
    +csstyle-button-variant(#a88cd5, #fff, #a88cd5)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#b094de, #fff, #b094de)

  // Warning
  @include option(warning)
    +csstyle-button-variant(#f58410, #fff, #f58410)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#ff9324, #fff, #ff9324)

  // Danger
  @include option(danger)
    +csstyle-button-variant(#f84545, #fff, #f84545)

    &:hover,
    &:active,
    &:focus
      +csstyle-button-variant(#ff5f5f, #fff, #ff5f5f)

  // ===========================================================
  // Disabled
  // ===========================================================

  // Disabled
  @include option(disabled)
    pointer-events: none
    cursor: not-allowed
    filter: alpha(opacity=65)
    opacity: .65

  // ===========================================================
  // Icon
  // ===========================================================
  @include option(icon)
    i
      padding-right: 3px

When i will release that code on github, people will get the possibility to download and import the component in their projects via bower.

For sure someone will want to add new colors or new sizes, I imagine something like that :

@include component(mybutton)

  // Here we import all options, part of the base button
  @include clone(button)

  // Now we can add parts or options
  @include option(xxl)
    +csstyle-button-size($csstyle-button-base-font-size * 2, $csstyle-button-base-padding-top-bottom * 1.6, $csstyle-button-base-padding-right-left * 1.8)

Make sense ?

@GesJeremie
Copy link
Author

So I just released my first component : http://csstyle-components.github.io/button/, and i'm waiting for other replies for that "issue", I think it's really important.

@keyurshah
Copy link

Very interested in this. A system to allow sharing and extending / modifying seems awesome

@geddski
Copy link
Owner

geddski commented Apr 24, 2015

@GesJeremie I thought of another simple way to accomplish this:

  1. Load the base button styles
  2. Override any component/options/parts etc by simply including the custom styles.

For example, let's say this is your base button definition:

@include component(button){
  background: blue;

  @include option(active){
    background: yellow;
  }
}

You can override any style of this base definition, and even add additional options like so:

@include component(button){

  @include option(warning){
    background: red;
  }

}

Notice that we didn't need to extend or inherit anything. The combined generated output of these files would then be:

.button {
  background: blue; 
}

.button.\--active {
  background: yellow; 
}

.button.\--warning {
  background: red; 
}

What do you think? The only gotcha would be making sure that the base styles are included before the user styles.

@geddski
Copy link
Owner

geddski commented Apr 24, 2015

PS awesome project you're working on!

@GesJeremie
Copy link
Author

@geddski I didn't try that but it make sense. Sounds perfect and already done ahaha :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants